[IOI2008] Type Printer 打印机
我们考虑如果打印结束时,不允许有部分字母留在打印机内。
这题应该怎么做
显然我们将所有要打印的字符串放入一棵Trie树
那么答案就是Trie树的节点数乘2+m
打印顺序只要沿树走即可
现在我们再来考虑打印结束时,允许有部分字母留在打印机内的情况
我们发现其实就是最后一个单词不用删除
那么我们让最长的一个单词最后输出即可
实现方式为,记录下最长的串后,在Trie树上打上标记
遍历Trie树时,碰到标记就最后访问
此处实现细节较多,要小心谨慎
总体实现如下:
#include <algorithm> #include <iostream> #include <cmath> #include <cstring> #include <map> #include <string> #include <vector> #include <queue> #include <stack> #include <cstdio> #include <cstdlib> using namespace std; typedef long long ll; inline int read() { register int p(1),a(0);register char ch=getchar(); while((ch<'0'||ch>'9')&&ch!='-') ch=getchar(); if(ch=='-') p=-1,ch=getchar(); while(ch>='0'&&ch<='9') a=a*10+ch-48,ch=getchar(); return a*p; } const int N=500010; int n,tot=0,root,all=0,finish; char du[N],ji[N],ans[1001000]; struct Trie { int nxt[26]; bool end,mark; }tree[N]; int newnode() { ++tot; memset(tree[tot].nxt,-1,sizeof(tree[tot].nxt)); return tot; } void insert(char *a) { int cur=root,len=strlen(a+1),idx; for(int i=1;i<=len;i++) { idx=a[i]-'a'; if(tree[cur].nxt[idx]==-1) tree[cur].nxt[idx]=newnode(); cur=tree[cur].nxt[idx]; } tree[cur].end=1; } void biao(char *a) { int cur=root,len=strlen(a+1),idx; for(int i=1;i<=len;i++) { idx=a[i]-'a'; cur=tree[cur].nxt[idx]; tree[cur].mark=1; } } void DFS(int xx) { if(tree[xx].end) ans[++all]='P'; int temp=-1,cur; for(int i=0;i<26;i++) if(tree[xx].nxt[i]!=-1) { cur=tree[xx].nxt[i]; if(!tree[cur].mark) { ans[++all]=i+'a'; DFS(tree[xx].nxt[i]); } else temp=i; } if(temp!=-1) ans[++all]=temp+'a',DFS(tree[xx].nxt[temp]); if(temp==-1&&tree[xx].mark) finish=1; if(!finish) ans[++all]='-'; } int main() { // freopen("input","r",stdin); // freopen("output","w",stdout); n=read(); root=newnode(); for(int i=1;i<=n;i++) { scanf("%s",du+1);insert(du); if(i==1||strlen(du+1)>strlen(ji+1)) strcpy(ji+1,du+1); } biao(ji); DFS(root); printf("%d\n",all); for(int i=1;i<=all;i++) printf("%c\n",ans[i]); return 0; }