题目的意思是有一个词典,然后给你一个字符串,把这个字符串按照词典当中的单词划分,问有多少种划分的方法?
比较容易想到的方法是对这个字符串的每一位进行枚举,找出以当前位为开始的字符的单词个数既d[i+len(x)] += d[i];但是如果是这样的话,每次要枚举词典,那样时间复杂度太高,所以就用trie树来构建字典,然后单词的长度为100,那么每一位的枚举就是最多100次,所以时间复杂度为O(字符串的长度*字典中最长单词的长度)。
#include <iostream>
#include "stdio.h"
#include "string.h"
using namespace std;
#define Mem(a, b) memset(a, b, sizeof(a))
const int maxNode = 400005;
const int mod = 20071027;
int dp[300005];
char sM[300005];
int nC;
char sS[105];
int ch[maxNode][26];
struct Trie{
bool val[maxNode];
int sz;
Trie(){
sz = 1;
Mem(ch, 0);
Mem(val, false);
}
int idx(char c) { return c - 'a'; }
void insert(char *s){
int u = 0, n = strlen(s);
for(int i = 0; i < n; i ++){
int v = idx(s[i]);
if(ch[u][v] == 0){
ch[u][v] = sz ++;
}
u = ch[u][v];
}
val[u] = true;
}
long long query(char *s){
int n = strlen(s);
Mem(dp, 0);
dp[0] = 0;
for(int i = 0; i < n; i ++){
int u = 0;
for(int j = i; j < n; j ++){
int v = idx(s[j]);
if(ch[u][v] == 0) break;
else if(val[ch[u][v]]){
dp[j] += ( i - 1 < 0 ? 1 : dp[i - 1]);
if(dp[j] >= mod)
dp[j] %= mod;
}
u = ch[u][v];
}
}
return dp[n-1];
}
};
int main(){
int cnt = 1;
while(cin>>sM){
Trie tmp;
cin>>nC;
for(int i = 0; i < nC; i ++){
cin>>sS;
tmp.insert(sS);
}
cout<<"Case "<<cnt++<<": "<<tmp.query(sM)<<endl;
}
return 0;
}