链接: Remember the Word
题意:
给一个 字符串 s 和 n个 字符串 问字符串 s 可以有多少种拆分方式 使得分成的每一个小段都可以从n个字符串中找到。
思路:
- 从后往前 dp ,dp [ i ] 代表从 位置 i 到字符串结尾的这一段的拆分方案 ,然后从后往前 ,对每个后缀进行查找 ,如果能找到长度为 x 的串 那么 dp[ i ] + = dp[ i + x ],依次更新,最后答案为 dp[ 0 ];
- 写了 n 个 strlen 然后 T l了 20 发 ,www (再用 strlen ,cin 我 。。。。。。。
代码:
#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<vector>
#include<cmath>
#include<string>
#include<map>
#include<queue>
using namespace std;
typedef long long ll;
const int maxn= 3e5+7 ;
const int mod= 20071027 ;
char str[4005][102], s[maxn] ;
int tot=1,tire[maxn][30],cnt[maxn],n;
int dp[maxn];
void insert(char *s) {
int p=0,len=strlen(s),t;
for(int i = 0; i < len; i ++) {
t = s[i] - 'a';
if(tire[p][t] == 0) {
memset(tire[tot],0,sizeof(tire[tot]));
tire[p][t]= tot ++;
}
p=tire[p][t];
}
cnt[p]++;
}
void find( char *s, int pos, int len) {
int p=0,t;
for(int i = pos; i < len; i++) {
t=s[i]-'a';
if(tire[p][t]==0) return ;
p=tire[p][t];
int ans= cnt[p] != 0 ? dp[i+1] : 0;
dp[pos] =(dp[pos]+ ans)%mod;
}
return ;
}
void init() {
memset(dp,0,sizeof(dp));
memset(tire[0],0,sizeof(tire[0]));
memset(cnt,0,sizeof(cnt));
tot=1;
}
int main () {
int ca=1;
while(scanf("%s%d",s,&n)!=EOF) {
init();
for(int i = 0; i < n; i ++) {
scanf("%s",str[i]);
insert(str[i]);
}
int len=strlen(s);
dp[len]=1;
for(int i=len-1; i>=0; i--) {
find( s, i, len );
}
printf ("Case %d: %d\n",ca++,dp[0]%mod);
}
}