hdu 5763 Another Meaning (KMP/哈希+DP)

题目大意:给你两个串,一长一短,如果长串中某个子串和短串完全相同,则这个子串可以被替换成"#",求长串所有的表达形式.......

比如"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

hdu 5763 Another Meaning (KMP/哈希+DP)的相关文章

HDU 5763 Another Meaning

HDU 5763 Another Meaning 题意:一个字串有可能在模式串出现多次,问有多少种可能出现的情况.关键是有重合的字串是不能同时计入的. 思路:先用kmp求出所有字串的位置.然后,dp. 二维的时候:dp[i][j] i表示前i个子串,j的值1表示一定用这个串,0表示不用.值表示字串出现的情况数. 一维的时候可以直接用dp[i] 表示前i个字串能出现的情况. 然后,状态转移就都是分为三种情况: 1)当前子串和前一个子串不冲突,dp[i] = dp[i-1] * 2. 或者 dp[i

hdu 5763 Another Meaning 哈希+dp

Another Meaning Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 917    Accepted Submission(s): 434 Problem Description As is known to all, in many cases, a word has two meanings. Such as “hehe”,

HDU 5763 Another Meaning(DP+KMP)

http://acm.hdu.edu.cn/showproblem.php?pid=5763 题意: 给出一个字符串和一个模式串,模式串有两种意思,问这句话有几种意思. 思路:因为肯定要去字符串去找模式串,所以首先用KMP计算next数组,然后用动态规划,d[i]表示分析到第i个字符时有多少种意思. 1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio>

【动态规划】【KMP】HDU 5763 Another Meaning

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5763 题目大意: T组数据,给两个字符串s1,s2(len<=100000),s2可以被解读成2种意思,问s1可以解读成几种意思(mod 1000000007). 题目思路: [动态规划][KMP] 题目有点绕,看看样例就懂了.其实不用KMP直接用substr就能做. 首先不解读成另一个意思的话,f[i]=f[i-1],接着如果当前位置能够与s2匹配,那么f[i]+=f[i-strlen(s2)]

HDU 5763 Another Meaning dp+字符串hash

题意:给定一个句子str,和一个单词sub,这个单词sub可以翻译成两种不同的意思,问这个句子一共能翻译成多少种不能的意思 例如:str:hehehe   sub:hehe 那么,有**he.he**.和hehehe三种不同的意思, 考虑一下aaadaaa这种情况?sub:aa  前面的aaa有三种,后面的aaa有三种,所以一共应该是有9种情况. 可以考虑成3*3=9 如果你考虑分块去相乘的话,那么恭喜你,你GG了.因为这样写非常复杂,而且非常难判断. 可以考虑下dp,因为注意到,它每个单词只有

HDU 5763 Another Meaning(FFT)

[题目链接] http://acm.hdu.edu.cn/showproblem.php?pid=5763 [题目大意] 给出两个串S和T,可以将S串中出现的T替换为*,问S串有几种表达方式. [题解] 我们定义数组f为S串中T出现的最后一个字母所在的位置,那么ans[i]=ans[i-1]+f[i-1]?ans[i-lenT]:0,一遍递推即可,所以关键就在于求出f数组了,f数组可以用kmp求,由于最近练FFT,用FFT求距离卷积匹配为0的位置,就是f数组了. [代码] #include <c

HDU 1686 Oulipo(KMP)

Problem Description The French author Georges Perec (1936–1982) once wrote a book, La disparition, without the letter 'e'. He was a member of the Oulipo group. A quote from the book: Tout avait Pair normal, mais tout s'affirmait faux. Tout avait Fair

hdu 3746 Cyclic Nacklace (KMP求最小循环节)

//len-next[len]为最小循环节的长度 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int len; char a[100010]; int next[100010]; void Getnext() { int i=0,j=-1; next[0]=-1; while(i<=len) { if(j==-1||a[i]==a[j]) i

hdu 1561The more, The Better(树形dp&amp;01背包)

The more, The Better Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4949    Accepted Submission(s): 2918 Problem Description ACboy很喜欢玩一种战略游戏,在一个地图上,有N座城堡,每座城堡都有一定的宝物,在每次游戏中ACboy允许攻克M个城堡并获得里面的宝