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

【扩展kmp】HDU 6153 A Secret

时间:2017-08-20 19:55:24      阅读:204      评论:0      收藏:0      [点我收藏+]

标签:ext   i++   最长公共前缀   isp   printf   时间复杂度   后缀   思路   tar   

acm.hdu.edu.cn/showproblem.php?pid=6153

【题意】

  • 给定字符串A和B,求B的所有后缀在A中出现次数与其长度的乘积之和
  • A和B的长度最大为1e6

【思路】

  • 把A和B同时反转,相当于求B的所有前缀在A中出现次数与其长度的乘积之和
  • 换个角度,相当于A中每出现一个B的前缀,答案中就要加上该前缀的长度
  • 考虑A中每个位置对答案的贡献,A[i...lenA-1]与B的最长公共前缀是x,则B中的前缀B[0...1],B[0....2]...B[0....x]都在A中出现,那么答案就要加上x*(x+1)/2
  • 求S中的每个后缀与T的最长公共前缀用扩展KMP,时间复杂度是线性的

【AC】

技术分享
 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=1e9+7;
 5 const int maxn=1e6+2;
 6 char s[maxn];
 7 char t[maxn];
 8 int nxt[maxn];
 9 int extend[maxn];
10 ll ans;
11 
12 void add(ll n)
13 {
14     ll tmp=((n%mod)*((n+1)%mod)/2)%mod;
15     ans=(ans+tmp)%mod;
16 }
17 void pre_EKMP(char x[],int m,int nxt[])
18 {
19     nxt[0]=m;
20     int j=0;
21     while(j+1<m && x[j]==x[j+1]) j++;
22     nxt[1]=j;
23     int k=1;
24     for(int i=2;i<m;i++)
25     {
26         int p=nxt[k]+k-1;
27         int L=nxt[i-k];
28         if(i+L<p+1) nxt[i]=L;
29         else
30         {
31             j=max(0,p-i+1);
32             while(i+j<m && x[i+j]==x[j]) j++;
33             nxt[i]=j;
34             k=i;
35         }
36     }
37 }
38 
39 void EKMP(char x[],int m,char y[],int n,int nxt[],int extend[])
40 {
41     pre_EKMP(x,m,nxt);//子串 
42     int j=0;
43     while(j<n && j<m &&x[j]==y[j]) j++;
44     extend[0]=j;
45     int k=0;
46     for(int i=1;i<n;i++)
47     {
48         int p=extend[k]+k-1;
49         int L=nxt[i-k];
50         if(i+L<p+1) extend[i]=L;
51         else
52         {
53             j=max(0,p-i+1);
54             while(i+j<n && j<m && y[i+j]==x[j]) j++;
55             extend[i]=j;
56             k=i;
57         }
58     }
59 }
60 
61 int main()
62 {
63     int T;
64     scanf("%d",&T);
65     while(T--)
66     {
67         scanf("%s",s);
68         scanf("%s",t);
69         int ls=strlen(s);
70         int lt=strlen(t);
71         for(int i=0;i<ls/2;i++)
72         {
73             swap(s[i],s[ls-1-i]);
74         }
75         for(int i=0;i<lt/2;i++)
76         {
77             swap(t[i],t[lt-1-i]);
78         }
79         EKMP(t,lt,s,ls,nxt,extend);
80         ans=0;
81         for(int i=0;i<ls;i++)
82         {
83             add(extend[i]);
84         }
85         printf("%I64d\n",ans);
86     }
87     return 0;
88 } 
扩展kmp

 

【扩展kmp】HDU 6153 A Secret

标签:ext   i++   最长公共前缀   isp   printf   时间复杂度   后缀   思路   tar   

原文地址:http://www.cnblogs.com/itcsl/p/7400730.html

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