码迷,mamicode.com
首页 > 其他好文 > 详细

CodeForces 432D Prefixes and Suffixes:KMP + dp

时间:2018-01-03 22:36:14      阅读:191      评论:0      收藏:0      [点我收藏+]

标签:cout   span   题解   color   题目   开始   子串   pre   链接   

题目链接:http://codeforces.com/problemset/problem/432/D

题意:

  给你一个字符串s,让你找出所有既是前缀又是后缀的子串,并输出它们分别出现了多少次。

 

题解:

  先对原串求一次nex数组。

  然后枚举位置i:

    sub(k)表示前缀s[0 to k]

    dp[i]表示sub(i)在原串s中的出现次数

    假设nex[i] = a, nex[a] = b, nex[b] = c ... nex[z] = -1

    则sub(a), sub(b), sub(c)...sub(z)均以s[i]结尾,dp[a...z]均+1。

  然而一个一个加会T...

  

  所以:

    初始时所有的 dp = 1

    每次:if(nex[i] != -1) dp[nex[i]] += dp[i]

    一路传递下去就好。

  

  最后从nex[len-1]开始往前跳nex。

  对于每次跳到的nex,sub(nex)一定也是s的后缀。

  此时输出它的出现次数dp[nex]。

  另外因为要顺着输出,而nex是倒着跳的,所以先存到stack里再输出。

 

AC Code:

 1 #include <iostream>
 2 #include <stdio.h>
 3 #include <string.h>
 4 #include <stack>
 5 #define MAX_N 100005
 6 
 7 using namespace std;
 8 
 9 int n;
10 int dp[MAX_N];
11 int nex[MAX_N];
12 char s[MAX_N];
13 
14 void cal_nex(char *p,int len)
15 {
16     nex[0]=-1;
17     int k=-1;
18     for(int i=1;i<len;i++)
19     {
20         while(k>-1 && p[i]!=p[k+1]) k=nex[k];
21         if(p[i]==p[k+1]) k++;
22         nex[i]=k;
23     }
24 }
25 
26 int main()
27 {
28     scanf("%s",s);
29     n=strlen(s);
30     cal_nex(s,n);
31     for(int i=0;i<n;i++) dp[i]=1;
32     for(int i=n-1;i>=0;i--)
33     {
34         if(nex[i]!=-1) dp[nex[i]]+=dp[i];
35     }
36     stack<int> stk;
37     int p=n-1;
38     while(p!=-1)
39     {
40         stk.push(p);
41         p=nex[p];
42     }
43     cout<<stk.size()<<endl;
44     while(!stk.empty())
45     {
46         int now=stk.top();
47         stk.pop();
48         cout<<now+1<<" "<<dp[now]<<endl;
49     }
50 }

 

CodeForces 432D Prefixes and Suffixes:KMP + dp

标签:cout   span   题解   color   题目   开始   子串   pre   链接   

原文地址:https://www.cnblogs.com/Leohh/p/8185474.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!