题目大意:给你两个串,一长一短,如果长串中某个子串和短串完全相同,则这个子串可以被替换成"#",求长串所有的表达形式.......
比如"hehehehe"和"hehe",则有5种情况,"#hehe","he#he","hehe#","##","hehehehe"
首先我们KMP/哈希找出长串中所有可以作为和短串结尾匹配成功后的位置
然后可以得到方程
(不是子串结尾)
(是子串结尾)
至于原因呢,如果它不是子串结尾,那么它不能被替换,所以是
而如果它是子串结尾,它既可以不被替换,即
也可以被替换,那么替换整个短串,转移的地方就是
然后转移一下即可,建议从1开始读入字符串方便转移
1 #include <cstdio> 2 #include <algorithm> 3 #include <cstring> 4 #define N 100100 5 #define mod 1000000007 6 #define ui unsigned int 7 #define ll long long 8 using namespace std; 9 10 int T,ls,lt; 11 int ed[N],nxt[N]; 12 ui f[N]; 13 char s[N],t[N]; 14 void get_kmp() 15 { 16 int i=1,j=0; 17 nxt[1]=0; 18 while(i<=lt) 19 { 20 if(j==0||t[i]==t[j]) 21 { 22 i++; 23 j++; 24 nxt[i]=j; 25 }else{ 26 j=nxt[j]; 27 } 28 } 29 } 30 void KMP() 31 { 32 int i=1,j=1; 33 while(i<=ls) 34 { 35 if(j==0||s[i]==t[j]) 36 { 37 i++; 38 j++; 39 }else{ 40 j=nxt[j]; 41 } 42 if(j==lt+1) 43 { 44 ed[i-1]=1; 45 j=nxt[j]; 46 } 47 } 48 } 49 ui solve() 50 { 51 f[0]=1; 52 for(int i=1;i<=ls;i++) 53 { 54 if(ed[i]==1) 55 { 56 f[i]=(f[i-lt]+f[i-1])%mod; 57 }else{ 58 f[i]=f[i-1]; 59 } 60 } 61 return f[ls]; 62 } 63 64 int main() 65 { 66 //freopen("aa.in","r",stdin); 67 scanf("%d",&T); 68 for(int i=1;i<=T;i++) 69 { 70 memset(nxt,0,sizeof(nxt)); 71 memset(ed,0,sizeof(ed)); 72 memset(f,0,sizeof(f)); 73 scanf("%s",s+1),ls=strlen(s+1); 74 scanf("%s",t+1),lt=strlen(t+1); 75 get_kmp(); 76 KMP(); 77 printf("Case #%d: %u\n",i,solve()); 78 } 79 return 0; 80 }
原文地址:https://www.cnblogs.com/guapisolo/p/9696928.html
时间: 2024-11-06 23:00:41