zoukankan      html  css  js  c++  java
  • 训练指南 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
    ", 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
    ", 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
    ", 1);
    32       else
    33     printf("%d
    ", 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
    ", 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('
    ');
    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:
    ", 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
    ", 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
    ", ret+1);
    45     }
    46     }
    47 }
    View Code

    11. uva 282 rename

    题意:

    方法:

    code:

    12. uva 475 wild thing

    题意:

    方法:

    code:

  • 相关阅读:
    小三学算术
    The Balance
    扫描线
    2019牛客暑期多校训练营(第九场)
    后缀数组
    Manacher
    局部变量和全局变量的区别
    2386:Lake Counting-poj
    简单背包问题(0032)-swust oj
    编程中易犯错误集锦-持续更新。。。。。
  • 原文地址:https://www.cnblogs.com/skyette/p/7980603.html
Copyright © 2011-2022 走看看