题意:给N个串,如果有一个串,其他所有的串都是它的子串,它是“字符统治者”,输入它,没有则输出No.
比赛用以前指针版AC自动机各种MLE,加释放内存TLE,还是得改模板,数组版AC(但还是没字典树的快)
#include<cstdio>
#include<cstring>
#include<queue>
#define maxn 100005
using namespace std;
int n;
struct Trie
{
int nxt[maxn][30],FAIL[maxn],edd[maxn],root,L;//nxt记录节点,在这里edd指针代表以当前节点为字符串尾的字符串个数
int newnode()
{
for(int i=0;i<26;i++)
nxt[L][i]=-1;//节点连接的边初始化为-1
edd[L]=0;
return L++;
}
void init()
{
L=0;
root=newnode();
}
void insert(char buf[],int l)//trie树的建立
{
int now=root;
for(int i=0;i<l;i++)
{
if(nxt[now][buf[i]-'a']==-1)nxt[now][buf[i]-'a']=newnode();
now=nxt[now][buf[i]-'a'];
}
edd[now]++;
}
void build()//建立ac自动机
{
queue<int>que;
for(int i=0;i<26;i++)
{
if(nxt[root][i]==-1)nxt[root][i]=root;
else //若有连边则将节点加入队列 ,并将FAIL指针指向root
{
FAIL[nxt[root][i]]=root;
que.push(nxt[root][i]);
}
}
while(!que.empty())
{
int now=que.front();
que.pop();
for(int i=0;i<26;i++)
{
if(nxt[now][i]==-1) //若无连边,则将该边指向当前节点FAIL指针指向的相应字符连接的节点
nxt[now][i]=nxt[FAIL[now]][i];
else //若有连边,则将儿子节点的FAIL指针指向当前节点FAIL指针指向相应字符接的节点
{
FAIL[nxt[now][i]]=nxt[FAIL[now]][i];
que.push(nxt[now][i]); //加入队列继续遍历
}
}
}
}
int query(char buf[],int l)
{
int now=root;
int res=0;
for(int i=0;i<l;i++)
{
now=nxt[now][buf[i]-'a'];
int temp=now;
while(temp!=root&& edd[temp]!=-1)//根据题目要求改变形式
{
res+=edd[temp];
edd[temp]=-1;
temp=FAIL[temp];
}
}
return res; //在这里返回的是匹配到的模式串的数量
}
};
char buf[maxn],ans[maxn];
Trie ac;
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&n);
ac.init();
int maxlen=-1;
for(int i=0;i<n;i++)
{
scanf("%s",buf);
int len=strlen(buf);
if(maxlen<len)
{
maxlen=len;
strcpy(ans,buf);
}
ac.insert(buf,len);
}
ac.build();
int sum=ac.query(ans,maxlen);
if(sum==n) puts(ans);
else puts("No");
}
}
Sunday,比赛时候WA了,可能是模板打错了。。
#include <iostream>
#include <cstring>
#include<string>
#include <cstdio>
using namespace std;
const int maxn=100005;
string str[maxn];
int sunday(char *text, char *patt)
{
size_t temp[256];
size_t *shift = temp;
size_t i, patt_size = strlen(patt), text_size = strlen(text);
// cout << "size : " << patt_size << endl;
for(i = 0; i < 256; i++)
{
*(shift+i) = patt_size + 1;
}
for(i = 0; i < patt_size; i++)
{
*(shift + (unsigned char)(*(patt+i))) = patt_size-i; // shift['s']=6步,shitf['e']=5以此类推
}
size_t limit = text_size - patt_size + 1;
for(i = 0; i < limit; i += shift[text[i + patt_size]])
{
if(text[i] == *patt)
{
char *match_text = text + i + 1;
size_t match_size = 1;
do
{
if(match_size == patt_size)
{
return 1;
}
}
while((*match_text++) == patt[match_size++]);
}
}
return 0;
}
int main(void){
ios::sync_with_stdio(false);
int T;
cin>>T;
while(T--)
{
int N;
cin>>N;
if(N==1)
{
cin>>str[0];
cout<<str[0]<<endl;
}
else{
int maxlen=0,maxpo=0;
bool bo=true;
for(int i=0;i<N;i++)
{
cin>>str[i];
int temp=str[i].length();
if(temp>maxlen)
{
maxlen=temp;
maxpo=i;
}
}
for(int i=0;i<N;i++)
{
if(i!=maxpo)
{
int ans=sunday((char *)str[maxpo].c_str(),(char *)str[i].c_str());
if(ans==0)
{
bo=false;
break;
}
}
}
if(bo==true)
cout<<str[maxpo]<<endl;
else
cout<<"No"<<endl;
}
}
return 0;
}
队友的字典树:
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <queue>
#include <cmath>
#include <cstring>
#include <stack>
#include <set>
#include <map>
#include <vector>
using namespace std;
#define INF 0x2fffffff
#define LL long long
#define MAX(a,b) ((a)>(b))?(a):(b)
#define MIN(a,b) ((a)<(b))?(a):(b)
#define id(a) ((a)-'a')
const int maxnode = 10000*50+10;
int ch[maxnode][26];
int val[maxnode];
int sz = 0;
int insert(char *s){
int len =strlen(s);
int u = 0;
for(int i = 0;i < len;i++){
int c = id(s[i]);
if(!ch[u][c]){
memset(ch[sz],0,sizeof(ch[sz]));
val[sz] = 0;
ch[u][c] = sz++;
}
u = ch[u][c];
}
val[u] ++;
}
int query(char *s){
int ans = 0;
for(int i = 0;s[i];i++){
int c = id(s[i]);
int u = 0;
int j = 0;
while(ch[u][c]){
if(val[ch[u][c]]){
ans += val[ch[u][c]];
val[ch[u][c]] = 0;
}
u = ch[u][c];
j ++;
c = id(s[i+j]);
}
}
return ans;
}
char s[100001];
int main(){
int t;
//freopen("1.txt","r",stdin);
//freopen("2.txt","w",stdout);
scanf("%d",&t);
while(t--){
int n;
scanf("%d",&n);
char a[100001];
memset(ch[0],0,sizeof(ch[0]));
val[0]= 0;
sz = 1;
int maxl=-1;
for(int i = 0;i < n;i++){
scanf("%s",a);
int len=strlen(a);
if(len>maxl)
{
memcpy(s,a,len+1);
maxl=len;
}
insert(a);
}
if(query(s)==n)printf("%s\n",s);
else printf("No\n");
}
return 0;
}
最后留个Sunday模板:
int SundaySearch(string text, string pattern){
int i = 0, j = 0, k;
int m = pattern.size();
if(pattern.size() <= 0 || text.size() <= 0)
return -1;
for(; i<text.size();) {
if(text[i] != pattern[j]) {
for(k=pattern.size() - 1; k>=0; k--) {
if(pattern[k] == text[m])
break;
}
i = m-k;
j = 0;
m = i+pattern.size();
}
else {
if(j == pattern.size()-1)
return i-j;
i++;
j++;
}
}
return -1;
}