(trie)BUAAOJ 371

题目链接

分别对名字和绰号建立2个trie树,其中记录树每个结点经过过多少次。

每个字符串在trie树中的路径都是固定的,故可以同时遍历两个树(某树不存在某个结点就停止这一侧的遍历),不妨设某一结点 名字树有x次经历,绰号树有y次经历。(不妨设x<=y),则任取y个绰号中的x个与这x个名字任意匹配,都会产生x个匹配,故加上x(实际操作中就是min(x,y))。(倒序考虑最终匹配方式,前面的过程任意匹配即可)一直重复该过程,所得答案即为总相似度最大的方式。

  1 #include <iostream>
  2 #include <string>
  3 #include <algorithm>
  4 #include <cstring>
  5 #include <cstdio>
  6 #include <cmath>
  7 #include <queue>
  8 #include <set>
  9 #include <map>
 10 #include <list>
 11 #include <vector>
 12 #include <stack>
 13 #define mp make_pair
 14 #define MIN(a,b) (a>b?b:a)
 15 #define rank rankk
 16 //#define MAX(a,b) (a>b?a:b)
 17 typedef long long ll;
 18 typedef unsigned long long ull;
 19 const int MAX=1e6+5;
 20 const int INF=1e9+5;
 21 const int B=1024;//桶的大小
 22 const double M=4e18;
 23 const int MAX_NODE=510000;
 24 const int sigma_size=26;
 25 using namespace std;
 26 //const int MOD=1e9+7;
 27 const int MOD=20071027;
 28 typedef pair<int,int> pii;
 29 const double eps=0.000000001;
 30 
 31 struct Trie
 32 {
 33     int ch[MAX_NODE][sigma_size];//点数、“字母”数
 34     int val[MAX_NODE];
 35     int num;//结点总数
 36     Trie(){num=1;memset(val,0,sizeof(val));memset(ch,0,sizeof(ch));}//初始时仅有根节点
 37     void clear() {num = 1;memset(ch, 0, sizeof(ch));memset(val,0,sizeof(val)); }
 38     int idx(char c)//返回对应字符的编号
 39     {
 40         return c-'a';
 41     }
 42     /*
 43         插入字符串s,附加信息为v。注意v必须非0,因为0代表:本结点不是单词结点
 44     */
 45     void insert(const char *s,int v)
 46     {
 47         int u=0,len=strlen(s);
 48         for(int i=0;i<len;i++)
 49         {
 50 //            ++val[u];
 51             int c=idx(s[i]);
 52             if(!ch[u][c])//结点不存在
 53             {
 54                 memset(ch[num],0,sizeof(ch[num]));
 55 //                val[num]=0;//中间节点的附加信息为0
 56 //                ++val[num];
 57                 ch[u][c]=num++;//新建结点
 58             }
 59             u=ch[u][c];//往下走
 60             ++val[u];
 61         }
 62 //        ++val[u];
 63 //        val[u]=v;//字符串的最后一个字符的附加信息为v
 64     }
 65     /*
 66      查询字符串的“附加信息”
 67      查询过程中间中断返回0
 68     */
 69     int check(char *s)
 70     {
 71         int u=0,len=strlen(s);
 72         for(int i=0;i<len;i++)
 73         {
 74             int c=idx(s[i]);
 75             if(!ch[u][c])
 76                 return 0;
 77             u=ch[u][c];
 78         }
 79         return val[u];
 80     }
 81     /*
 82     找字符串s的长度不超过len的前缀
 83     */
 84     void find_prefixes(const char *s,int len,vector <int> &ans)
 85     {
 86         int u=0;
 87         for(int i=0;i<len;i++)
 88         {
 89             if(s[i]=='\0')
 90                 break;
 91             int c=idx(s[i]);
 92             if(!ch[u][c])
 93                 break;
 94             u=ch[u][c];
 95             if(val[u]!=0)//过程中所有找到的全都push进去
 96                 ans.push_back(val[u]);
 97         }
 98     }
 99 };
100 Trie t1,t2;
101 int n;
102 char tem[MAX];
103 ll an;
104 void dfs(int lo1,int lo2)
105 {
106     an+=min(t1.val[lo1],t2.val[lo2]);
107     for(int i=0;i<26;i++)
108     {
109         if(t1.ch[lo1][i]&&t2.ch[lo2][i])
110             dfs(t1.ch[lo1][i],t2.ch[lo2][i]);
111     }
112 }
113 int main()
114 {
115     while(~scanf("%d",&n))
116     {
117         t1.clear();t2.clear();
118         for(int i=0;i<n;i++)
119         {
120             scanf("%s",tem);
121             t1.insert(tem,1);
122         }
123         for(int i=0;i<n;i++)
124         {
125             scanf("%s",tem);
126             t2.insert(tem,1);
127         }
128         an=0;
129         dfs(0,0);
130         printf("%lld\n",an);
131     }
132 }

 

posted @ 2017-05-24 11:03  perplex  阅读(246)  评论(0)    收藏  举报