2017中國大學生程序設計競賽 - 網絡選拔賽 HDU 6153 A Secret KMP,思維
阿新 • • 發佈:2017-08-19
show while += long long problem sizeof 中國大學 print pac
題目鏈接:http://acm.hdu.edu.cn/showproblem.php?pid=6153
題意:給了串s和t,要求每個t的後綴在在s中的出現次數,然後每個次數乘上對應長度求和。
解法:關鍵在於想到把s和t都翻轉之後,把t求next,然後用t去匹配s,在匹配過程中把fail指針跳到的地方加1,但是還沒完,最後需要反向遍歷第二個串將大串對小串的貢獻加上去就可以了。
這道題是很多現場AC的代碼是有漏洞的,比如bazbaba,bazbaba這個答案是34,但是很多現場AC的代碼會輸出31。。。敝隊就是這樣,然而AC了。。。
#include <bits/stdc++.h> using namespace std; typedef long long LL; const int maxn = 1e6+7; const int mod = 1e9+7; char s[maxn],t[maxn]; int n, m, fail[maxn], cnt[maxn]; int main() { int T; scanf("%d", &T); while(T--) { scanf("%s", s+1); scanf("%s", t+1); n = strlen(s+1); m = strlen(t+1); reverse(s+1, s+n+1); reverse(t+1, t+m+1); int j=0; for(int i=2; i<=m; i++){ while(j>0&&t[i]!=t[j+1]) j=fail[j]; if(t[i]==t[j+1])j++; fail[i]=j; } memset(cnt, 0, sizeof(cnt)); j=0; for(int i=1; i<=n; i++){ while(j>0&&t[j+1]!=s[i]) j=fail[j]; if(t[j+1]==s[i]) j++; cnt[j]++; } for(int i=m; i>=1; i--){ cnt[fail[i]]+=cnt[i]; } int ans=0; for(int i=1; i<=m; i++){ ans += (LL)cnt[i]*i%mod; ans %= mod; } printf("%d\n", ans); } return 0; }
2017中國大學生程序設計競賽 - 網絡選拔賽 HDU 6153 A Secret KMP,思維