zoukankan      html  css  js  c++  java
  • P3294 [SCOI2016]背单词

    P3294 [SCOI2016]背单词

    首先发现一个性质就是我们务必要求一个字符串的后缀串的编号必须在这个串前面

    对于这样的多串前后缀关系的问题,我们可以使用 Trie 树来解决,但是这里是后缀,于是翻转一下再用 Trie。

    然后发现把这个要求建到 Trie 树上,然后缩点就是:给一个树标号,要求子节点编号必须大于父亲节点编号,并使得 (sum_{u} sum_{(u,v)in E}{w[u]-w[son]}) 最小。

    发现答案就是按照子树 (siz) 排序过后的 (dfs) 序,比较简单,证明略,具体见题解。

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
    	x=0;char ch=getchar();bool f=false;
    	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
    	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
    	x=f?-x:x;
    	return ;
    }
    
    template <typename T>
    inline void write(T x){
    	if(x<0) putchar('-'),x=-x;
    	if(x>9) write(x/10);
    	putchar(x%10^48);
    	return ;
    }
    const int N=5e5+5;
    int n,m,a[N],cur,DFN,siz[N],fa[N];
    struct Trie{
    	int ch[26],tag;
    	#define ch(x,i) t[x].ch[i]
    	#define tag(x) t[x].tag
    }t[N];
    void Insert(char *str){
    	int len=strlen(str),p=0;
    	for(int i=0;i<len;i++){
    		int c=str[i]-'a';
    		if(!ch(p,c)) ch(p,c)=++cur;
    		p=ch(p,c);
    	}
    	tag(p)=true;
    	return ;
    }
    char s[N];
    int head[N],to[N],nex[N],idx;
    inline void add(int u,int v){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	head[u]=idx;
    	return ;
    }
    
    void Dfs1(int x,int f){
    	siz[x]=1;
    	for(int i=0;i<26;i++) if(ch(x,i)) Dfs1(ch(x,i),tag(x)?x:f);
    	if(tag(x)) add(f,x),siz[f]+=siz[x],fa[x]=f;
    	return ;
    } 
    #define PII pair<int,int>
    #define ll long long
    ll Ans;
    int dfn[N]; 
    void Dfs2(int x){
    	int top=0;
    	vector<PII> tmp;
    	if(x!=0) dfn[x]=++DFN;
    	if(fa[x]) Ans+=dfn[x]-dfn[fa[x]];
    	else Ans+=dfn[x];
    	for(int i=head[x];i;i=nex[i]) tmp.push_back(make_pair(siz[to[i]],to[i])),top++;
    	sort(tmp.begin(),tmp.end());
    	for(int i=0;i<top;i++) Dfs2(tmp[i].second);
    	return ;
    } 
    int main(){
    	read(n);
    	for(int i=1;i<=n;i++) scanf("%s",s),reverse(s,s+strlen(s)),Insert(s);
    	Dfs1(0,0);
    	Dfs2(0);
    	write(Ans);
        return 0;
    }
    
  • 相关阅读:
    ArcGIS Engine 常用方法(转)
    正则表达式 C#System.Text.RegularExpressions.Regex
    ae中栅格数据转为矢量数据 (转)
    ArcEngine 渲染的使用 (转)
    C#字符串分割成数组,中间多空格
    <C++ GUI Programming with Qt4 ,Second Edition> 学习笔记
    perl module and its package
    static_cast reinterpret_cast
    阅读<inside the c++ object modle > 有感
    C++ virtual table
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14691182.html
Copyright © 2011-2022 走看看