• F


    题目链接:https://cn.vjudge.net/contest/283743#problem/F

    题目大意:给你一个字符串,然后让你求出不同的子串的个数。

    具体思路:首先,一个字符串中总的子串个数是len*(len+1)/2,然后就开始去重了,通过height数组,求出所有重复的子串的个数,然后就用总的子串的个数-重复的子串的个数就可以了。

    AC代码:

     1 #include<iostream>
     2 #include<stack>
     3 #include<cstring>
     4 #include<iomanip>
     5 #include<stdio.h>
     6 #include<algorithm>
     7 #include<cmath>
     8 using namespace std;
     9 # define ll long long
    10 const int maxn = 5e5+100;
    11 int cntA[maxn], cntB[maxn], sa[maxn], tsa[maxn], A[maxn], B[maxn], height[maxn];
    12 int Rank[maxn];
    13 char ch[maxn];
    14 ll n;
    15 //sa[i]代表第i小的后缀位置,Rank[i]代表第i位置开始的后缀在所有的后缀串中排名第几
    16 // height[i]代表排名第i个字符串和第i-1个字符串的相同前缀的长度
    17 void cal()
    18 {
    19     for(int i = 0; i < 256; i++) cntA[i] = 0;
    20     for(int i = 1; i <= n; i++) cntA[ch[i-1]]++;
    21     for(int i = 1; i < 256; i++) cntA[i] += cntA[i-1];
    22     for(int i = n; i; i--) sa[cntA[ch[i-1]]--] = i;
    23     Rank[sa[1]] = 1;
    24     for(int i = 2; i <= n; i++)
    25     {
    26         Rank[sa[i]] = Rank[sa[i-1]];
    27         if(ch[sa[i]-1] != ch[sa[i-1]-1]) Rank[sa[i]]++;
    28     }
    29     for(int l = 1; Rank[sa[n]] < n; l <<= 1)
    30     {
    31         memset(cntA, 0, sizeof(cntA));
    32         memset(cntB, 0, sizeof(cntB));
    33         for(int i = 1; i <= n; i++)
    34         {
    35             cntA[A[i] = Rank[i]]++;
    36             cntB[B[i] = (i+l <= n)?Rank[i+l]:0]++;
    37         }
    38         for(int i = 1; i <= n; i++) cntB[i] += cntB[i-1];
    39         for(int i = n; i; i--) tsa[cntB[B[i]]--] = i;
    40         for(int i = 1; i <= n; i++) cntA[i] += cntA[i-1];
    41         for(int i = n; i; i--) sa[cntA[A[tsa[i]]]--] = tsa[i];
    42         Rank[sa[1]]=1;
    43         for(int i = 2; i <= n; i++)
    44         {
    45             Rank[sa[i]] = Rank[sa[i-1]];
    46             if(A[sa[i]] != A[sa[i-1]] || B[sa[i]] != B[sa[i-1]]) Rank[sa[i]]++;
    47         }
    48     }
    49     for(int i = 1, j = 0; i <= n; i++)
    50     {
    51         if(j) j--;
    52         while(ch[i+j-1] == ch[sa[Rank[i]-1] + j - 1]) j++;
    53         height[Rank[i]] = j;
    54     }
    55 }
    56 int main()
    57 {
    58     int T;
    59     scanf("%d",&T);
    60     while(T--)
    61     {
    62         scanf("%s",ch);
    63        n=strlen(ch);
    64         if(n==1)
    65         {
    66             printf("1
    ");
    67             continue;
    68         }
    69         // cout<<1<<endl;
    70         cal();
    71         ll ans=n*(n+1)/2;
    72         //cout<<ans<<endl;
    73         for(int i=2; i<=n; i++)
    74         {
    75             ans-=height[i];
    76          // cout<<i<<" "<<height[i]<<endl;
    77         }
    78         printf("%lld
    ",ans);
    79     }
    80     return 0;
    81 }
  • 相关阅读:
    Cocos Creator Editor 第一个编辑器扩展(扩展菜单)
    Rider 设置
    unity 使用GameObject.SetActive(true)激活对象时,会在SetActive内部调用Awake和OnEnable函数
    unity/C# 结构体属性使用set和get访问器应注意的问题
    unity 自定义AssetImporter导入指定资源
    Duilib部分源码解析
    TreeView树形控件的使用
    JQuery 文档资源收集
    排序和搜索(一)插入排序系列
    字符相关类型和编码概念
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10387024.html
Copyright © 2020-2023  润新知