思路:
每个串可以用多次且每个串的长度<=1000,那么就简单了。
字符串可以字典树或者hash维护,然后暴搞就好了,记录一下路径,然后输出就好了。
1e6的字符串hash复杂度还是可观的
复杂度:O(N*W)
//#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
typedef long long LL;
const int Maxm = 1e5 + 10;
const int Maxn = 1e4 + 10;
const LL p = 31;
const LL mod = 1e9 + 7;
char s1[Maxn], s2[Maxm][1010];
LL h1[Maxn], f[Maxn];
map<LL, LL>mp;
int n, m, Mx;
void init(){
h1[0] = 0;
f[0] = 1;
for(int i=1;i<=10000;i++) f[i] = f[i-1] * p % mod;
}
LL idx(char x){
if(x >= 'A' && x <= 'Z') return (long long)(x - 'A' + 1);
return (long long)(x - 'a' + 1);
}
LL Hash(char s[]){
LL temp = 0;
int len = strlen(s+1);
Mx = Mx < len ? len : Mx;
for(int i=1;i<=len;i++)
temp=(temp*p+idx(s[i])) % mod;
return temp;
}
LL get_L_to_R(int Left, int Right, LL has[]){
return (has[Right] - has[Left-1]* f[Right - Left + 1] % mod + mod) % mod;
}
void jud(LL x, LL y){
if(mp.find(x) != mp.end()) return;
mp[x] = y;
}
int dp[Maxn], pre[Maxn], ans[Maxn];
int main(){
init();
scanf("%d%s", &n, s1+1);
int len = strlen(s1+1);
reverse(s1+1, s1+len+1);
for(int i=1;i<=len;i++)
h1[i]=(h1[i-1]*p+idx(s1[i])) % mod;
scanf("%d", &m);
Mx = 0;
for(int i=1;i<=m;i++){
scanf("%s", s2[i]+1);
jud(Hash(s2[i]), i);
}
memset(dp, 0, sizeof(dp));
pre[0] = -1;
dp[0] = 1;
LL has1, has2;
for(int i=1;i<=len;i++){
for(int j=1;j<=Mx && i-j>=0;j++){
if(dp[i-j]){
has1 = get_L_to_R(i-j+1, i, h1);
if(mp.find(has1) != mp.end()){
pre[i] = i-j;
ans[i] = mp[has1];
dp[i] = 1;
break;
}
}
}
}
int pos = len;
while(pre[pos] != -1){
printf("%s ",s2[ans[pos]] + 1);
pos = pre[pos];
}
return 0;
}