随机数据下,时间复杂度应该是碾压哈希的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); }