http://codeforces.com/problemset/problem/432/D
题目大意:
给出一个字符串,求有多少种长度的前缀和后缀相等,并且得到的这个子串在原字符串中出现的次数。
思路:预处理kmp,发现从n开始的next[n]一直往下都是合法的前缀后缀,先记录下来,然后从n往1dp,每次都是
dp[i]++,dp[next[i]]+=dp[i],这样转移之后再输出即可。
1 #include<cstdio> 2 #include<cmath> 3 #include<algorithm> 4 #include<cstring> 5 #include<iostream> 6 char s[200005]; 7 int n,p[200005],c[200005],dp[200005]; 8 int read(){ 9 int t=0,f=1;char ch=getchar(); 10 while (ch<‘0‘||ch>‘9‘){if (ch==‘-‘) f=-1;ch=getchar();} 11 while (‘0‘<=ch&&ch<=‘9‘){t=t*10+ch-‘0‘;ch=getchar();} 12 return t*f; 13 } 14 int main(){ 15 scanf("%s",s+1); 16 n=strlen(s+1); 17 p[1]=0;int j=0; 18 for (int i=2;i<=n;i++){ 19 while (j>0&&s[j+1]!=s[i]) j=p[j]; 20 if (s[j+1]==s[i]) j++; 21 p[i]=j; 22 } 23 int tot=0; 24 for (int i=p[n];i;i=p[i]){ 25 c[++tot]=i; 26 } 27 for (int i=n;i;i--){ 28 dp[i]++; 29 dp[p[i]]+=dp[i]; 30 } 31 printf("%d\n",tot+1); 32 for (int i=tot;i>=1;i--){ 33 printf("%d %d\n",c[i],dp[c[i]]); 34 } 35 printf("%d 1\n",n); 36 return 0; 37 }
时间: 2024-10-11 22:35:32