随机数据下,时间复杂度应该是碾压哈希的hhh
大小写是不重要的,因为第一步总是会把大写改成小写
所以我们可以暂时把字符集的大小都变成小写去匹配
然后拿样例来说
iherehtolleh
我们匹配这个,其实可以把这个串反过来
hellotherehi
然后匹配这个玩意,最后把答案倒过来就好了
这个串匹配的结果就是
我们定义为匹配
是否有可能
假如暴力枚举个字符复杂度上天
不妨对这个串建立
自动机,暴力跳
转移
#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e6+10;
string s[maxn];
char a[maxn],b[maxn];
int n,m,len[maxn],f[maxn],pre[maxn];
int ed[maxn],fail[maxn],zi[maxn][26],id;
void insert(int num)
{
int l = len[num], now = 0;
for(int i=0;i<l;i++)
{
int c = s[num][i]-'a';
if( s[num][i]>='A'&&s[num][i]<='Z' ) c = s[num][i]-'A';
if( !zi[now][c] ) zi[now][c] = ++id;
now = zi[now][c];
}
ed[now] = num;
}
void get_fail()
{
queue<int>q;
for(int i=0;i<=25;i++) if( zi[0][i] ) q.push( zi[0][i] );
while( !q.empty() )
{
int u = q.front(); q.pop();
for(int i=0;i<=25;i++)
{
if( zi[u][i] ) fail[zi[u][i]] = zi[fail[u]][i],q.push( zi[u][i] );
else zi[u][i] = zi[fail[u]][i];
}
}
}
void dfs(int x)
{
if( x==0 ) return;
cout << s[pre[x]] << " ";
dfs( x-len[pre[x]] );
}
int main()
{
scanf("%d%s",&n,a+1);
for(int i=1;i<=n;i++) b[i] = a[n-i+1];
scanf("%d",&m);
for(int i=1;i<=m;i++)
{
cin >> s[i]; len[i] = s[i].length();
insert( i );
}
get_fail();
f[0] = 1;
int now = 0;
for(int i=1;i<=n;i++)
{
now = zi[now][b[i]-'a'];
for(int t=now;t;t=fail[t] )
{
if( ed[t]==0 ) continue;
if( f[i-len[ed[t]]]==0 ) continue;
f[i] = 1; pre[i] = ed[t];
break;
}
}
dfs(n);
} 
京公网安备 11010502036488号