题意就是求子串在主串中的出现次数。
然后这里的子串是环形的,所以要特别处理一下,然后使用过的子串后面不能再去匹配。
首先,对于环形子串,我们化环为链然后慢慢取一段段来匹配即可。
显然这里是kmp匹配。然后map标记下是否出现过。
暴力的回溯的话就是找到了i = i-t.size()-1,j = 0。
这题数据范围比较小,也可以过。
考虑优化一下:
因为nxt[i]满足和前缀相同,那么,如果匹配到了一个。
那么对于子串T,因为它的前缀和后缀相同,那么显然现在后缀就可以当做前缀去匹配下一个位置。
所以优化就是i不动,j = nxt[j]
// Author: levil #include<bits/stdc++.h> using namespace std; typedef long long LL; typedef pair<string,int> pii; const int N = 1e3+5; const int M = 2e5+5; const LL Mod = 1e9+7; #define rg register #define pi acos(-1) #define INF 1e9 #define CT0 cin.tie(0),cout.tie(0) #define IO ios::sync_with_stdio(false) #define dbg(ax) cout << "now this num is " << ax << endl; namespace FASTIO{ inline LL read(){ LL x = 0,f = 1;char c = getchar(); while(c < '0' || c > '9'){if(c == '-') f = -1;c = getchar();} while(c >= '0' && c <= '9'){x = (x<<1)+(x<<3)+(c^48);c = getchar();} return x*f; } void print(int x){ if(x < 0){x = -x;putchar('-');} if(x > 9) print(x/10); putchar(x%10+'0'); } } using namespace FASTIO; void FRE(){/*freopen("data1.in","r",stdin); freopen("data1.out","w",stdout);*/} int nxt[N]; void Pre_nxt(string s) { int len = s.size(); nxt[0] = -1; int i = 0,k = -1; while(i < len) { if(k == -1 || s[i] == s[k]) nxt[++i] = ++k; else k = nxt[k]; } } int kmp(string s,string t) { int len = s.size(),ans = 0; int i = 0,j = 0; while(i < len) { if(j == -1 || s[i] == t[j]) { i++,j++; if(j == t.size()) ans++,j = nxt[j]; } else j = nxt[j]; } return ans; } int main() { IO;CT0; string a,b; while(cin >> a >> b) { unordered_map<string,int> mp; int ans = 0,len = b.size(); b += b; for(rg int i = 0;i < len;++i) { string t = ""; for(rg int j = i;j < i+len;++j) t += b[j]; if(mp[t] != 0) continue; Pre_nxt(t); mp[t]++; ans += kmp(a,t); } cout << ans << endl; } system("pause"); }