标签:each int pac ext 从后往前 too 前缀 span tor
InputThe first line is a single integer T, indicating the number of test cases.
For each case, the first line is an integer n (1 <= n <= 200000), which is the length of string s. A line follows giving the string s. The characters in the strings are all lower-case letters.
OutputFor each case, output only one number: the sum of the match times for all the prefixes of s mod 10007.Sample Input
1 4 abab
Sample Output
6
题意:找每个前缀在字符串中的出现次数
题解:kmp的next数组处理,刚开始从后往前遍历,每个next数值往前递归加上次数,最后就是结果,交了之后发现tle(没有发现最差的时间复杂度居然有O(n*n)),于是乎只能改进一下,用num数组来存次数,每次递归的时候就把当前num++,这样只需要遍历一遍就行了
时间复杂度变成了O(n)果然不会Tle了
#include<map> #include<set> #include<cmath> #include<queue> #include<stack> #include<vector> #include<cstdio> #include<iomanip> #include<cstdlib> #include<cstring> #include<iostream> #include<algorithm> #define pi acos(-1) #define ll long long #define mod 10007 #define ls l,m,rt<<1 #define rs m+1,r,rt<<1|1 using namespace std; const double g=10.0,eps=1e-9; const int N=200000+5,maxn=60+5,inf=0x3f3f3f3f; ll num[N]; int Next[N],slen; string str; void getnext() { int k=-1; Next[0]=-1; for(int i=1;i<slen;i++) { while(k>-1&&str[k+1]!=str[i])k=Next[k]; if(str[k+1]==str[i])k++; Next[i]=k; } } int main() { ios::sync_with_stdio(false); cin.tie(0); // cout<<setiosflags(ios::fixed)<<setprecision(2); int t,n; cin>>t; while(t--){ cin>>n>>str; slen=str.size(); getnext(); ll ans=0; memset(num,0,sizeof num); for(int i=slen-1;i>=0;i--) { ll j=i; while(j!=-1)num[j]++,j=Next[j]; } for(int i=0;i<slen;i++)ans=ans%mod+num[i]%mod; cout<<ans<<endl; } return 0; }
标签:each int pac ext 从后往前 too 前缀 span tor
原文地址:http://www.cnblogs.com/acjiumeng/p/6819026.html