HDU

来源:互联网 发布:干湿两用吸尘器 知乎 编辑:程序博客网 时间:2024/06/10 22:58

题目链接


题意:


给定一个字符串和模板串,告诉你模板串有2个意思,问这个字符串总共有多少种含义。


思路:

    头一次见这么用KMP的.

   dp[i]表示以i字符串结尾的串的总含义数.

   那么有dp【i】=dp[i-1] 如果他可以和模式串匹配,dp[i-1]表示他不表示模式串的那个意思.

   如果 主串中第i个位置往前lenb个字符构成的串和模式串匹配,dp[i]=(dp[i-1]+dp[i-lenb]);

   表示匹配模式串的那个意思.

   那么问题转化成了如果快速找到当前位置i前面lenb长度的串是否和模式串匹配.

   数据比较水我暴力也水过去了,但是如果出个全一样的串就是O(N2)就T了.

   比较好的方法就是:

我们都知道给你一个主串和模式串,问你主串中出现了几个模式串,我们KMP。当j==lenb,cnt++.

这个题就利用那个原理,我们匹配到j==lenb时就把主串第i个字符标记一下,含义就是当前i字符往前lenb个字符的字符串可以和模式串匹配.这样就实现了O(N)预处理O(1)查询.

#include<bits/stdc++.h>using namespace std;typedef long long ll;const ll mod = 1e9+7;const int maxn = 1e5+10;char a[maxn],b[maxn];ll dp[maxn];bool mat[maxn];int nxt[maxn]; void get_nxt()  {      int len = strlen(b+1);    nxt[1] = -1;      int i = 1,j = 0;      while(i <= len)      {          if(j == 0 || b[i] == b[j])          nxt[++i] = ++j;          else          j = nxt[j];      }   }void KMP()  {      int i=1,j=1;int lena = strlen(a+1);int lenb = strlen(b+1);      while(i<=lena)     {          if(j==0||a[i]==b[j])          {              if(j==lenb)              {                  mat[i] = 1;                 j=nxt[j];              }              else              {                  i++,j++;              }          }          else          j=nxt[j];      }      return ;  }  int main(){int _;cin>>_;int t = 0;while(_--){memset(dp,0,sizeof dp);memset(mat,0,sizeof mat);scanf("%s %s",a+1,b+1);int lena=strlen(a+1);int lenb=strlen(b+1);get_nxt();dp[0] = 1;KMP();for(int i = 1;i <= lena;i++){dp[i] = dp[i-1];if(mat[i])dp[i] = (dp[i] + dp[i-lenb])%mod;}printf("Case #%d: %lld\n",++t,dp[lena]);}return 0;}

原创粉丝点击