[BZOJ]3012: [Usaco2012 Dec]First! trie树+拓扑排序

题解: 首先可以知道 某一个串存在前缀串则这个串必然不能字典序最小  所以我们直接对长度排序然后逐次加入trie树中  然后我们考虑当前串能成为最小 必须一层层满足对应的限制条件 然后拓扑check一下就行了

#include <algorithm>
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <string>
#include <queue>
#include <cmath>
#include <set>
#include <map>
#define mp make_pair
#define pb push_back
#define pii pair<int,int>
#define link(x) for(edge *j=h[x];j;j=j->next)
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,r,l) for(int i=r;i>=l;i--)
const int MAXN=3e5+10;
const double eps=1e-8;
#define ll long long
using namespace std;
struct edge{int t;edge*next;}e[905],*h[26],*o=e;
void add(int x,int y){o->t=y;o->next=h[x];h[x]=o++;}
ll read(){
    ll x=0,f=1;char ch=getchar();
    while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}

typedef struct node{
    int id;string s;
}node;
node str[MAXN];

bool cmp(node aa,node bb){return aa.s.length()<bb.s.length();}

typedef struct Node{
    int ch[26],sz,id;
}Node;
Node d[MAXN];
int rt,cnt;
void newnode(int &x){
    x=++cnt;
    d[x].sz=d[x].id=0;
    for(int i=0;i<26;i++)d[x].ch[i]=0;
}

void insert(string s,int id){
    int len=s.length();int temp=rt;
    bool flag=0;
    for(int i=0;i<len;i++){
	int t=s[i]-'a';
	if(!d[temp].ch[t]){break;}
	temp=d[temp].ch[t];
	if(d[temp].id){flag=1;break;}
    }
    if(flag)return ;
    temp=rt;
    for(int i=0;i<len;i++){
	int t=s[i]-'a';
	if(!d[temp].ch[t])newnode(d[temp].ch[t]);
	temp=d[temp].ch[t];d[temp].sz++;
    }
    d[temp].id=id;
}

int Edge[31][31];
bool vis[MAXN];
int du[MAXN],ans1;
queue<int>que;
bool check(){
    inc(i,0,25)if(!du[i])que.push(i);
    while(!que.empty()){
	int x=que.front();que.pop();
	link(x){
	    du[j->t]--;
	    if(!du[j->t])que.push(j->t);
	}
    }
    inc(i,0,25)if(du[i])return 0;
    return 1;
}

void dfs(int x){
    if(d[x].id){
	memset(h,0,sizeof(h));o=e;
	inc(i,0,25)du[i]=0;
	inc(i,0,25)inc(j,0,25)if(Edge[i][j])add(i,j),du[j]++;
	if(check())vis[d[x].id]=1,ans1++;
	return ;
    }
    for(int i=0;i<26;i++){
	if(!d[x].ch[i])continue;
	for(int j=0;j<26;j++){
	    if(j!=i&&d[x].ch[j])Edge[i][j]++;
	}
	dfs(d[x].ch[i]);
	for(int j=0;j<26;j++){
	    if(j!=i&&d[x].ch[j])Edge[i][j]--;
	}	
    }
}

string S[MAXN];

int main(){
    ios::sync_with_stdio(false);
    ans1=0;
    int n;cin>>n;
    inc(i,1,n)cin>>str[i].s,str[i].id=i,S[i]=str[i].s;
    sort(str+1,str+n+1,cmp);
    inc(i,1,n)insert(str[i].s,str[i].id);
    dfs(rt);
    cout<<ans1<<"\n";
    inc(i,1,n)if(vis[i])cout<<S[i]<<"\n";
}

  

3012: [Usaco2012 Dec]First!

Time Limit: 10 Sec  Memory Limit: 128 MB
Submit: 328  Solved: 159
[Submit][Status][Discuss]

Description

Bessie has been playing with strings again. She found that by changing the order of the alphabet she could make some strings come before all the others lexicographically (dictionary ordering). For instance Bessie found that for the strings "omm", "moo", "mom", and "ommnom" she could make "mom" appear first using the standard alphabet and that she could make "omm" appear first using the alphabet "abcdefghijklonmpqrstuvwxyz". However, Bessie couldn't figure out any way to make "moo" or "ommnom" appear first. Help Bessie by computing which strings in the input could be lexicographically first by rearranging the order of the alphabet. To compute if string X is lexicographically before string Y find the index of the first character in which they differ, j. If no such index exists then X is lexicographically before Y if X is shorter than Y. Otherwise X is lexicographically before Y if X[j] occurs earlier in the alphabet than Y[j].

给定n个总长不超过m的互不相同的字符串,现在你可以任意指定字符之间的大小关系。问有多少个串可能成为字典
序最小的串,并输出这些串。n <= 30,000 , m <= 300,000

Input

* Line 1: A single line containing N (1 <= N <= 30,000), the number of strings Bessie is playing with.

* Lines 2..1+N: Each line contains a non-empty string. The total number of characters in all strings will be no more than 300,000. All characters in input will be lowercase characters 'a' through 'z'. Input will contain no duplicate strings.

Output

 * Line 1: A single line containing K, the number of strings that could be lexicographically first.

 * Lines 2..1+K: The (1+i)th line should contain the ith string that could be lexicographically first. Strings should be output in the same order they were given in the input. 

Sample Input

4
omm
moo
mom
ommnom
INPUT DETAILS: The example from the problem statement.

Sample Output

2
omm
mom

OUTPUT DETAILS: Only "omm" and "mom" can be ordered first.
posted @ 2019-01-29 14:00  wang9897  阅读(202)  评论(0编辑  收藏  举报