训练指南 string easy

https://vjudge.net/contest/202728#problem/A

 

1. uva 11488 Hyper Prefix Sets

题意:给了一些string,定义其一个subset的价值为subset中所有string的longest common prefix(LCP)的长度 乘 subset的大小。让你找出最大的价值。

方法:将所有字符串插入字典树,可以边插边更新答案,或者查完后遍历字典树更新。

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 
12 const int maxn = 2e2+1;
13 char str[maxn], prefix[maxn];
14 
15 int read()
16 {
17   gets(str);
18   int ret = 0;
19   char *tmp = str;
20   while (*tmp)
21     {
22       ret = ret*10 + (*tmp-'0');
23       ++tmp;
24     }
25   //  cerr << "read " << ret << endl;
26   return ret;
27 }
28 
29 const int N = 1e7+1;
30 int g[N][2], sz, cnt[N];
31 inline int newnode()
32 {
33   memset(g[sz], 0, sizeof(g[sz]));
34   cnt[sz] = 0;
35   return sz++;
36 }
37 inline void init()
38 {
39   sz = 0;
40   newnode();
41 }
42 inline void Max(int &a, const int &b)
43 {
44   if (a < b)
45     a = b;
46 }
47 int main()
48 {
49   int T = read();
50   for (int kase = 1; kase <= T; ++kase)
51     {
52       int n = read();
53       init();
54       int ans = 0;
55       for (int i = 0; i < n; ++i)
56     {
57       gets(str);
58       int len = strlen(str);
59       for (int i = 0, j = 0; i < len; ++i)
60         {
61           int c = str[i]-'0';
62           if (!g[j][c])
63         g[j][c] = newnode();
64           j = g[j][c];
65           ++cnt[j];
66           Max(ans, cnt[j]*(i+1));
67         }
68     }
69       printf("%d\n", ans);
70     }
71   
72 }
View Code

 

2. uva 1519 Dictionary Sets

题意:给了一些string,让你生成一个dictionary。dictionary中的字符串可以是原来的string,也可以是形如prefix' + suffix', 其中prefix'要是某个原string的prefix,suffix'要是某个原string的suffix。问你dictionary的大小是多少

方法:

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 
12 const int N = 4e5+1, A = 26;
13 
14 struct Trie
15 {
16   int g[N][A], sz, cnt[A];
17   inline int newnode()
18   {
19     memset(g[sz], 0, sizeof(g[sz]));
20     return sz++;
21   }
22   inline void init()
23   {
24     sz = 0;
25     newnode();
26     memset(cnt, 0, sizeof(cnt));
27   }
28   inline void insert(char *str)
29   {
30 
31     int len = strlen(str);
32     for (int i = 0, j = 0; i < len; ++i)
33       {
34     int c = str[i]-'a';
35     if (!g[j][c])
36       {
37         g[j][c] = newnode();
38         if (i)
39           cnt[c] += 1;
40       }
41     j = g[j][c];
42       }
43   }
44   inline void binsert(char *str)
45   {
46 
47     int len = strlen(str);
48     for (int i = 0, j = 0; i < len; ++i)
49       {
50     int c = str[len-1-i]-'a';
51     if (!g[j][c])
52       {
53         g[j][c] = newnode();
54         if (i)
55           cnt[c] += 1;
56       }
57     j = g[j][c];
58       }
59   }
60 } prefix, suffix;
61 char str[50];
62 inline bool read(int &a)
63 {
64   if (gets(str) == NULL)
65     return false;
66   char *tmp = str;
67   a = 0;
68   while (*tmp)
69     {
70       a = 10*a + *tmp-'0';
71       ++tmp;
72     }
73   //  cerr << "read " << a << endl;
74   return true;
75 }
76 int vis[A];
77 int main()
78 {
79   int n;
80   while (read(n))
81     {
82       prefix.init();
83       suffix.init();
84       memset(vis, 0, sizeof(vis));
85       for (int i = 0; i < n; ++i)
86     {
87       gets(str);
88       prefix.insert(str);
89       suffix.binsert(str);
90       int len = strlen(str);
91       if (len == 1)
92         vis[str[0]-'a'] = 1;
93     }
94       ll ans = 1ll*(prefix.sz-1)*(suffix.sz-1);
95       for (int c = 0; c < 26; ++c)
96     ans -= 1ll*prefix.cnt[c]*suffix.cnt[c]-vis[c];
97       printf("%lld\n", ans);
98     }
99 }
View Code

 

3. uva 1399 puzzle

题意:告诉你字母表的大小和一些禁止串,让你找出最长的可行串。

方法:AC自动机上的DP

code:

 

4. uva 10298 power strings

题意:定义了string的power,给你若干询问,每次求出一个string的最大幂数。

方法:求周期问题

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 const int maxn = 1e6+1;
12 
13 char s[maxn];
14 int f[maxn];
15 
16 int main()
17 {
18   while (gets(s))
19     {
20       int len = strlen(s);
21       if (len == 1 && s[0] == '.')
22     break;
23       for (int i = 0, j = f[0] = -1; i < len; ++i, ++j)
24     {
25       while (j != -1 && s[i] != s[j])
26         j = f[j];
27       f[i+1] = j+1;
28     }
29       int pick = len-f[len];
30       if (len % pick)
31     printf("%d\n", 1);
32       else
33     printf("%d\n", len/pick);
34     }
35 }
View Code

 

5. uva 10887 concatenation of languages

题意:给你两个string set A 和 B,让你求 ||{a+b, string a in A and string b in B}|| .

方法:哈希(?)。暴力枚举插入std::set<string>。注意有坑点,可能输入空串。

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 
12 string a[1500];
13 char s[11];
14 inline string get()
15 {
16   gets(s);
17   return string(s);
18 }
19 
20 set<string> st;
21 int main()
22 {
23   int T;
24   scanf("%d", &T);
25   for (int kase = 1; kase <= T; ++kase)
26     {
27       int n, m;
28       scanf("%d %d", &n, &m);
29       get();
30       for (int i = 0; i < n; ++i)
31     a[i] = get();
32       st.clear();
33       for (int i = 0; i < m; ++i)
34     {
35       string tmp = get();
36       for (int j = 0; j < n; ++j)
37         st.insert(a[j]+tmp);
38     }
39       printf("Case %d: %d\n", kase, (int)st.size());
40     }
41 }
View Code

 

6. uva 11475 extend to palindrome

题意:给你一个字符串,让你在其后方加最少的字符,使得新字符串是个回文串。

方法:用str' 来表示 str的reverse, 注意原串S可以写成 A+B, 其中B是一个回文串(B = B', 可以为空)。最后得到的回文串为 A+B+A',A'为新增的部分。所以我们只需要B的长度最大,或者说S的后缀和S'的前缀的公共部分最大。很多种求法,匹配就可以。

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 
12 const int maxn = 1e5+1;
13 char s[maxn];
14 int f[maxn];
15 
16 int main()
17 {
18   while (~scanf("%s", s))
19     {
20       int n = strlen(s);
21       for (int i = 0,  j = f[0] = -1; i < n; ++i, ++j)
22     {
23       while (j != -1 && s[n-1-i] != s[n-1-j])
24         j = f[j];
25       f[i+1] = j+1;
26     }
27       int i, j;
28       for (i = 0, j = 0; i < n; ++i)
29     {
30       while (j != -1 && s[i] != s[n-1-j])
31         j = f[j];
32       j += 1;
33     }
34       printf("%s", s);
35       while (j < n)
36     {
37       putchar(s[n-1-j]);
38       ++j;
39     }
40       putchar('\n');
41     }
42 }
View Code

 

7. uva 12338 anti-rhyme pairs

题意:给了一组string str[],多个询问,每个询问形如(i, j), 让你输出str[i] 和 str[j] 的最长公共前缀的长度(LCP)。

方法:建立字典树,用end[i] 表示 str[i] 在字典树上的终止位置(终止结点),h[node] 表示 node节点在字典树上的高度(即所对应字符串的长度),那么询问(i, j)的答案就是h[lca(end[i], end[j])]。所以对字典树求lca即可。

code:

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 typedef long long ll;
  5 typedef pair<int, int> ii;
  6 typedef pair<ll, ll> l4;
  7 
  8 #define pb push_back
  9 #define mp make_pair
 10 
 11 
 12 const int N = 1e6+10;
 13 const int A = 26;
 14 vector<int> g[N];
 15 
 16 int ch[N][A], szs, v[100001];
 17 inline int newnode()
 18 {
 19   memset(ch[szs], 0, sizeof(ch[szs]));
 20   g[szs].clear();
 21   return szs++;
 22 }
 23 inline void init()
 24 {
 25   szs = 0;
 26   newnode();
 27 }
 28 
 29 inline int insert(char *str)
 30 {
 31   int len = strlen(str);
 32   int cur = 0;
 33   for (int i = 0; i < len; ++i)
 34     {
 35       int c = str[i]-'a';
 36       if (!ch[cur][c])
 37     ch[cur][c] = newnode(), g[cur].pb(ch[cur][c]);
 38       cur = ch[cur][c];
 39     }
 40   return cur;
 41 }
 42 int sz[N], h[N], top[N], par[N];
 43 int n, m;
 44 char str[N];
 45 void dfs(int cur)
 46 {
 47   sz[cur] = 1;
 48   for (int i = 0; i < g[cur].size(); ++i)
 49     {
 50       int nxt = g[cur][i];
 51       par[nxt] = cur;
 52       h[nxt] = h[cur]+1;
 53       dfs(nxt);
 54       sz[cur] += sz[nxt];
 55     }
 56 }
 57 void hl(int cur)
 58 {
 59   int son = -1;
 60   int sonsz = 0;
 61   for (int i = 0; i < g[cur].size(); ++i)
 62     {
 63       int nxt = g[cur][i];
 64       if (sz[nxt] > sonsz)
 65     {
 66       sonsz = sz[nxt];
 67       son = nxt;
 68     }
 69     }
 70   if (son != -1)
 71     top[son] = top[cur], hl(son);
 72   for (int i = 0; i < g[cur].size(); ++i)
 73     {
 74       int nxt = g[cur][i];
 75       if (nxt != son)
 76     top[nxt] = nxt, hl(nxt);
 77     }
 78 }
 79 int lca(int a, int b)
 80 {
 81   while (top[a] != top[b])
 82     {
 83       if (h[top[a]] < h[top[b]])
 84     swap(a, b);
 85       a = par[top[a]];
 86     }
 87   if (h[a] > h[b])
 88     return b;
 89   else
 90     return a;
 91 }
 92 int main()
 93 {
 94   int T;
 95   scanf("%d", &T);
 96   for (int kase = 1; kase <= T; ++kase)
 97     {
 98       printf("Case %d:\n", kase);
 99       scanf("%d", &n);
100       init();
101       for (int i = 1; i <= n; ++i)
102     {
103       scanf("%s", str);
104       v[i] = insert(str);
105     }
106       par[0] = -1;
107       h[0] = 0;
108       top[0] = 0;
109       dfs(0);
110       hl(0);
111       scanf("%d", &m);
112       for (int i = 1; i <= m; ++i)
113     {
114       int uu, vv;
115       scanf("%d %d", &uu, &vv);
116       printf("%d\n", h[lca(v[uu], v[vv])]);
117     }
118     }
119 }
View Code

 

8. uva 1556 disk tree

题意:给定多个文件路径,让你输出所有显示过的文件层次。

方法:

code:

 

9. uva 257 palinwords

题意:给你若干string,对于每一个string,如果他包含至少两个长度超过2、本质不同且互不包含的回文字串,就输出他。

方法:首先只需考虑长度为3和4的回文子串。

code:

 

10. uva 261 the window property

题意:定义一个string合法:如果对于每一个k <= strlen, 都有 ||set{ substring of length k }|| <= k+1。然后给你一个string,让你判断他是否合法,如果不合法输出第一个导致他不合法的位置(即这个位置之前的前缀是合法的。

方法:暴力,对于一个询问,记录下每个k值所对应的set。从左到右一次添加字符,每次添加第i(从1开始算)个字符,产生了i个新的substring,更新,判断是否合法。

code:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 typedef long long ll;
 5 typedef pair<int, int> ii;
 6 typedef pair<ll, ll> l4;
 7 
 8 #define pb push_back
 9 #define mp make_pair
10 
11 const int maxn = 1e2+1;
12 set<string> g[maxn];
13 
14 string str;
15 int solve()
16 {
17   int len = str.length();
18   for (int i = 1; i <= len; ++i)
19     g[i].clear();
20   for (int i = 0; i < len; ++i)
21     {
22       for (int k = 1; k <= i+1; ++k)
23     {
24       g[k].insert(str.substr(i+1-k, k));
25       if (g[k].size() > k+1)
26         return i;
27     }
28     }
29   return -1;
30 }
31 char s[maxn];
32 int main()
33 {
34   while (gets(s) != NULL)
35     {
36       str = string(s);
37       int ret = solve();
38       if (ret == -1)
39     {
40       puts("YES");
41     }
42       else
43     {
44       printf("NO:%d\n", ret+1);
45     }
46     }
47 }
View Code

 

11. uva 282 rename

题意:

方法:

code:

 

12. uva 475 wild thing

题意:

方法:

code:

 

posted @ 2017-12-05 01:43  大四开始ACM  阅读(225)  评论(0编辑  收藏  举报