[树形dp][trie]cf856B Similar Words
来源:互联网 发布:家里有网络怎么看电视 编辑:程序博客网 时间:2024/06/16 02:12
Description
Let us call a non-empty sequence of lowercase English letters a word. Prefix of a word x is a word y that can be obtained from x by removing zero or more last letters of x.
Let us call two words similar, if one of them can be obtained from the other by removing its first letter.
You are given a set S of words. Find the maximal possible size of set of non-empty words X such that they satisfy the following:
- each word of X is prefix of some word from S;
- X has no similar words.
Input
Input data contains multiple test cases. The first line of the input data contains an integer
t — the number of test cases. The descriptions of test cases follow.
The first line of each description contains an integern — the number of words in the setS(1 ≤ n ≤ 106 ). Each of the following n lines contains one non-empty word — elements ofS . All words inS are different.
It is guaranteed that the total length of all words in one input data doesn’t exceed106 .
Output
For each test case print one line that contains one integer
m — the maximal number of words that X can contain.
Sample Input
2
3
aba
baba
aaab
2
aa
a
Sample Output
6
1
在一棵树上,相邻的点不能同时取,问最多取多少个点。
dp[i][0]代表不取本点,子树的答案,dp[i][1]代表取,树形dp采用dfs实现即可。
树的构造过程为similiar words之间连边。至于为什么形成的是树,可以采用反证法证明没有偶环(最长的前缀只能连接一个similar word),而奇环显然不存在。
#include<bits/stdc++.h>using namespace std;const int maxn = 1e6 + 5;const int maxm = 26;int tot, n;int ch[maxn][maxm];int newNode(){ memset(ch[tot], 0, sizeof ch[tot]); return tot++;}char s[maxn];void add(char *s){ int len = strlen(s); int cur = 0; for(int i = 0; i < len; ++ i) { int v = s[i] - 'a'; if(ch[cur][v] == 0) ch[cur][v] = newNode(); cur = ch[cur][v]; }}string str[maxn];vector<int> G[maxn];void buildGraph(const string &s){ int a = 0; int b = ch[0][s[0]-'a']; for(int i = 1; i < s.size(); ++ i) { int v = s[i] - 'a'; a = ch[a][v]; b = ch[b][v]; if(a == 0 || b == 0) return; G[a].push_back(b); G[b].push_back(a); }}int f[maxn][2];bool vis[maxn];void dfs(int u){ vis[u] = true; f[u][0] = 0; f[u][1] = 1; for(auto v : G[u]) { if(vis[v]) continue; dfs(v); f[u][0] += max(f[v][0], f[v][1]); f[u][1] += f[v][0]; }}int main(){ int T; cin >> T; while(T--) { tot = 1; cin >> n; memset(ch[0], 0, sizeof ch[0]); for(int i = 0; i < n; ++ i) { scanf("%s", s); add(s); str[i] = s; } for(int i = 1; i < tot; ++ i) G[i].clear(); for(int i = 0; i < n; ++ i) buildGraph(str[i]); for(int i = 1; i <= tot; ++ i) vis[i] = false; int res = 0; for(int i = 1; i < tot; ++ i) { if(!vis[i]) { dfs(i); res += max(f[i][0], f[i][1]); } } cout << res << endl; } return 0;}
- [树形dp][trie]cf856B Similar Words
- Codeforces Similar Words [trie树+树形dp]
- Similar words
- jzoj 5040. 【NOI2017模拟4.2】押韵 trie树+树形dp
- pku1816 Wild Words (trie)
- HDU1247Hat’s Words--Trie
- trie+dp
- xtu-1269 Similar Subsequence(dp+树状数组)
- POJ1816 Wild Words Trie+Dfs
- HDOJ 1247 -- Hat Words Trie
- POJ1816--Wild Words(Trie+搜索)
- HDU1247 Hat’s Words【Trie】
- Hat's Words hdu1247 trie
- 树形dp
- 树形DP
- 树形dp
- 树形DP
- 树形dp
- Python 函数式编程(一)
- 2-3 冒泡排序
- 让你越来越值钱的秘密:目标清单
- NOIP模拟9.13
- Virus_JS3_PyAnalysisAndSummary
- [树形dp][trie]cf856B Similar Words
- Python函数式编程之lambda
- 知识点1
- 下载CentOS
- 前后端分离
- 3171: [Tjoi2013]循环格
- 写程序学ML:K近邻(KNN)算法原理及实现(一)
- secureCRT连接linux
- R实战:【常用函数】transform对列数据加工生成新列