zoukankan      html  css  js  c++  java
  • POJ 3376 Finding Palindromes EX-KMP+字典树

    题意:

    给你n个串串,每个串串可以选择和n个字符串拼接(可以自己和自己拼接),问有多少个拼接后的字符串是回文。

    所有的串串长度不超过2e6;

    题解:

    这题由于是在POJ上,所以string也用不了,会tle。

     串串个数也比较多,开不下二维的char数组,卡内存。

    所以数据的预处理需要处理成一个串串,把所有的串串放在一个串里面。

    记录每一个串串的起始位置和长度。

    数据预处理部分就解决了。

    然后就是核心思想部分了。

    首先你要知道如何用EX_KMP求串串前缀和后缀是否是回文。(其实也可以用马拉车)

    其实这个就是t串等于s串的反串,然后做一个EX_KMP就可以了。

    不会的可以做做这一题  Best Reward HDU - 3613

    于是我们处理出了所有串串的前缀和后缀是否是一个回文。

    下面看这个例子 dedabc 和 cba 这个显然就是可以拼接成回文的。

    由此很容易想到用字典树写这一题。

    然后有3种情况

    1、s的长度 > t的长度,t的反串是s的前缀,s剩下的部分是回文串。

    2、s的长度 < t的长度,s的反串是t的前缀,t剩下的部分是回文串。

    3、s的长度 = t的长度,t的反串等于s。

    然后就是具体做法,正串放入字典树内,如果某个位置的的下一个位置pos是一个回文(这个根据上面的EX_KMP处理出来)val[pos]++;

    插入完后就在最后一个节点的位置pos,ed[pos]++;

    最后一步计算答案;

    字典树里面存的是正串,所以查询使用反串去进行匹配,

    第1种情况,假设当前节点为u,对于当前节点i,当i<len-1且从第i+1个字母往后是一个回文串的时候,ans+=ed[u]。

    第2种情况,如果我们顺利的查找到s反串的尾节点u,则ans+=val[u]。

    第3种情况,假设当前节点为u,对于当前节点i,当i==len-1的时候,ans+=ed[u]。

    最近正在学习串串,这是我遇到的第一道需要思考的题目,感觉还是可以的。

    博客鸽了这么久,是时候开始写了。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <queue>
      4 #include <cmath>
      5 #include <algorithm>
      6 #include <set>
      7 #include <iostream>
      8 #include <map>
      9 #include <stack>
     10 #include <string>
     11 #include <time.h>
     12 #include <vector>
     13 #define  pi acos(-1.0)
     14 #define  eps 1e-9
     15 #define  fi first
     16 #define  se second
     17 #define  rtl   rt<<1
     18 #define  rtr   rt<<1|1
     19 #define  bug         printf("******
    ")
     20 #define  mem(a,b)    memset(a,b,sizeof(a))
     21 #define  name2str(x) #x
     22 #define  fuck(x)     cout<<#x" = "<<x<<endl
     23 #define  f(a)        a*a
     24 #define  sf(n)       scanf("%d", &n)
     25 #define  sff(a,b)    scanf("%d %d", &a, &b)
     26 #define  sfff(a,b,c) scanf("%d %d %d", &a, &b, &c)
     27 #define  sffff(a,b,c,d) scanf("%d %d %d %d", &a, &b, &c, &d)
     28 #define  pf          printf
     29 #define  FRE(i,a,b)  for(i = a; i <= b; i++)
     30 #define  FREE(i,a,b) for(i = a; i >= b; i--)
     31 #define  FRL(i,a,b)  for(i = a; i < b; i++)+
     32 #define  FRLL(i,a,b) for(i = a; i > b; i--)
     33 #define  FIN         freopen("data.txt","r",stdin)
     34 #define  gcd(a,b)    __gcd(a,b)
     35 #define  lowbit(x)   x&-x
     36 #define rep(i,a,b) for(int i=a;i<b;++i)
     37 #define per(i,a,b) for(int i=a-1;i>=b;--i)
     38 using namespace std;
     39 typedef long long  LL;
     40 typedef unsigned long long ULL;
     41 const int maxn = 2e6 + 7;
     42 const int maxm = 8e6 + 10;
     43 const int INF = 0x3f3f3f3f;
     44 const int mod = 10007;
     45 int nxt[maxn], extend[maxn], len[maxn], vis[2][maxn];
     46 char s[maxn], t[maxn];
     47 void pre_EKMP ( char x[], int m, int nxt[] ) {
     48     nxt[0] = m;
     49     int j = 0;
     50     while ( j + 1 < m && x[j] == x[j + 1] ) j++;
     51     nxt[1] = j;
     52     int k = 1;
     53     for ( int i = 2; i < m; i++ ) {
     54         int p = nxt[k] + k - 1;
     55         int L = nxt[i - k];
     56         if ( i + L < p + 1 ) nxt[i] = L;
     57         else {
     58             j = max ( 0, p - i + 1 );
     59             while ( i + j < m && x[i + j] == x[j] ) j++;
     60             nxt[i] = j;
     61             k = i;
     62         }
     63     }
     64 }
     65 void EKMP ( char x[], int m, char y[], int n, int nxt[], int extend[], int _L, int flag ) {
     66     pre_EKMP ( x, m, nxt );
     67     int j = 0;
     68     while ( j < n && j < m && x[j] == y[j] ) j++;
     69     extend[0] = j;
     70     int k = 0;
     71     for ( int i = 1; i < n; i++ ) {
     72         int p = extend[k] + k - 1;
     73         int L = nxt[i - k];
     74         if ( i + L < p + 1 ) extend[i] = L;
     75         else {
     76             j = max ( 0, p - i + 1 );
     77             while ( i + j < n && j < m && y[i + j] == x[j] ) j++;
     78             extend[i] = j;
     79             k = i;
     80         }
     81     }
     82     for ( int i = 0 ; i < n ; i++ )
     83         vis[flag][_L + i] = ( i + extend[i] == n );
     84 }
     85 
     86 struct Trie {
     87     int ch[maxn][26], val[maxn], ed[maxn];
     88     int sz;
     89     void init() {
     90         memset ( ch[0], 0, sizeof ( ch[0] ) );
     91         sz = 0, val[0] = 0, ed[0] = 0;
     92     }
     93     void add ( char *s, int n, int L ) {
     94         int u = 0;
     95         for ( int i = 0; i < n; i++ ) {
     96             int id = s[i] - 'a';
     97             val[u] += vis[0][L + i];
     98             if ( !ch[u][id] ) {
     99                 ch[u][id] = ++sz;
    100                 memset ( ch[sz], 0, sizeof ( ch[sz] ) );
    101                 val[sz] = 0;
    102                 ed[sz] = 0;
    103             }
    104             u = ch[u][id];
    105         }
    106         ed[u]++;
    107     }
    108     int find ( char *s, int n, int L ) {
    109         int u = 0, ret = 0;
    110         for ( int i = 0; i < n; i++ ) {
    111             int id = s[i] - 'a';
    112             u = ch[u][id];
    113             if ( !u ) break;
    114             if ( ( i < n - 1 && vis[1][L + i + 1] ) || i == n - 1 )
    115                 ret += ed[u];
    116         }
    117         if ( u ) ret += val[u];
    118         return  ret;
    119     }
    120 } trie;
    121 int n;
    122 int main() {
    123     while ( ~sf ( n ) ) {
    124         mem ( vis, 0 );
    125         trie.init();
    126         int tot = 0;
    127         for ( int i = 0; i < n ; i++ ) {
    128             scanf ( "%d%s", &len[i], s + tot );
    129             memcpy ( t + tot, s + tot, len[i] );
    130             reverse ( t + tot, t + tot + len[i] );
    131             EKMP ( t + tot, len[i], s + tot, len[i], nxt, extend, tot, 0 );
    132             EKMP ( s + tot, len[i], t + tot, len[i], nxt, extend, tot, 1 );
    133             trie.add ( s + tot, len[i], tot );
    134             tot += len[i];
    135         }
    136         LL ans = 0;
    137         tot = 0;
    138         for ( int i = 0 ; i < n ; i++ ) {
    139             ans += trie.find ( t + tot, len[i], tot );
    140             tot += len[i];
    141         }
    142         printf ( "%lld
    ", ans );
    143     }
    144     return 0;
    145 }
    View Code
  • 相关阅读:
    Python—re模块
    Python—json模块
    Python—sys模块介绍
    Python—os模块介绍
    Python—randonm模块介绍
    Python—time模块介绍
    Python—包介绍
    Python—模块介绍
    Python—装饰器
    jvm、jre、jdk
  • 原文地址:https://www.cnblogs.com/qldabiaoge/p/11310169.html
Copyright © 2011-2022 走看看