首页 > 其他分享 >字符串杂题

字符串杂题

时间:2022-11-22 21:48:23浏览次数:66  
标签:int 杂题 pos 合法 100010 字符串 include border

字符串杂题。

P5446 [THUPC2018]绿绿和串串

一个回文中心 \(i\),如果右端点能到字符串末尾,或者左端点能到开头且 \(2i-1\) 合法,则 \(i\) 合法。马拉车乱搞就行了,记得清空。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
char ch[1000010],s[2000010];
int f[2000010];
int n;
bool v[2000010];
int main(){
    int tim;scanf("%d",&tim);
    while(tim--){
        scanf("%s",ch+1);n=2*strlen(ch+1)+1;
        for(int i=1;i<=n;i++){
            if(i&1)s[i]='#';
            else s[i]=ch[i>>1];
        }
        s[0]='~';
        int r=0,mid=0;
        for(int i=1;i<=n;i++){
            if(i<=r)f[i]=min(f[2*mid-i],r-i+1);
            while(s[i+f[i]]==s[i-f[i]])f[i]++;
            if(i+f[i]>r)r=i+f[i]-1,mid=i;
        }
        int len=n>>1;
        for(int i=n-1;i>=1;i-=2){
            int pos=i>>1;
            if(pos+(f[i]-1>>1)==len||(pos-(f[i]-1>>1)==1&&v[2*pos-1]))v[pos]=true;
        }
        for(int i=1;i<=len;i++)if(v[i])printf("%d ",i);
        printf("\n");
        for(int i=1;i<=n;i++)v[i]=false,s[i]=f[i]=0;
    }
    return 0;
}

P3546 [POI2012]PRE-Prefixuffix

首先两个循环相等的串可以被拆成 \(ST,TS\) 的形式。那么 \(S\) 就是 border。问题是怎么求 \(T\)。

写一个border子串查询 \(O(\log n)\) 单次找,巨大难写还不知道能不能过

(这玩意怎么写:建SAM后扫描线树剖线段树,详见P4482 [BJWC2018]Border 的四种求法

当然我不会后缀。然后发现 \(S\) 从 \(\left \lfloor \dfrac n2\right\rfloor\) 开始往左右缩小,中间的border似乎有着某种单调性,最多只会扩展 \(1\) 长度,然后就是往下减。那么哈希就行了,整个指针单调扫一遍,复杂度 \(O(n)\)。

CF526D Om Nom and Necklace

看到题第一眼找周期,kmp就行了,只要周期整除 \(\left\lfloor \dfrac ik\right\rfloor\)。然后问题是找后面那一小截 \(A\)。这个其实可以直接 Z 函数。合法段可以扩展到 \(s[1\dots n]\) 和 \(s[i\dots n]\) 的 lcp 和 \(|A|\) 的最小值。

CF432D Prefixes and Suffixes

这不板板题吗。不会的参阅oiwiki的kmp的“统计每个前缀的出现次数”部分。

不懂哪里需要 exkmp。

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>
#include <random>
#include <cstring>
using namespace std;
char s[100010];
int n,top,nxt[100010],cnt[100010];
void getnxt(){
    for(int i=2,j=0;i<=n;i++){
        while(j&&s[i]!=s[j+1])j=nxt[j];
        if(s[i]==s[j+1])j++;
        nxt[i]=j;
    }
}
pair<int,int>ans[100010];
int main(){
    scanf("%s",s+1);n=strlen(s+1);
    getnxt();
    for(int i=1;i<=n;i++)cnt[nxt[i]]++;
    for(int i=n;i>=1;i--)cnt[nxt[i]]+=cnt[i];
    for(int i=1;i<=n;i++)cnt[i]++;
    int x=n;
    while(x){
        ans[++top]=make_pair(x,cnt[x]);x=nxt[x];
    }
    sort(ans+1,ans+top+1);
    printf("%d\n",top);
    for(int i=1;i<=top;i++)printf("%d %d\n",ans[i].first,ans[i].second);
    return 0;
}

P3538 [POI2012]OKR-A Horrible Poem

又是子串查询border

啊枚举因数能过啊,那没事了。我看这玩意还以为是线性的。

这题枚举因数其实可以直接把所有质因子扫下来然后一个一个除,判是否合法,合法就除掉,不合法不管。

P3426 [POI2005]SZA-Template

一个 \(i\) 长度的前缀合法当且仅当是 border,且 border 树上所有子树节点差的最大值不超过 \(i\) 。树上问题,爆扫就行。

标签:int,杂题,pos,合法,100010,字符串,include,border
From: https://www.cnblogs.com/gtm1514/p/16916521.html

相关文章

  • 鏖战字符串
    C:鏖战字符串时间限制: 1Sec  内存限制: 128MB题目描述Abwad在nbc即将完成她的程序的时候,急中生智拔掉了她电脑的电源线,争取到了宝贵的时间。作为著名论文《论Ct......
  • JS前期数组、字符串、时间、定时器、DOM\BOM事件方法等总结
    1.字符串方法        .charAt(对应字符元素下标)——根据下标查找字符串内元素        .charCodeAt(对应字符元素下标)——根据下标查找字符串某元素在u......
  • 第五节、字符串
    第五节、字符串第一节基础知识1.每个字符都有对应的整数ASCII码,常用ASCII值,’A''Z'是6590,‘a''z'是97122,’0‘’9'是4857,字符可以参与运算,运算时会将其当作整数。(记住)......
  • 字符串
    字符串比较          字符串理解       ......
  • 20221122-Python格式化字符串
    1.格式化字符串       ......
  • FileReader之获取文本文件内容为字符串
    FileReader之获取文本文件内容为字符串FileReader官网描述:FileReader对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用File或Blob......
  • C语言字符串
    文章目录​​一、字符串的概念​​​​二、占用内存的情况​​​​三、字符串的初始化​​​​四、字符串与指针​​​​五、字符串的结尾标志​​​​六、字符串的输出​​......
  • Newtonsoft的高级玩法,让你的json字符串与众不同
    json一经出现就得到多很多开发员的青睐,数据传输直接取代了之前的xml格式,不过也确实非常好用。关于json的常用操作,可以参考这篇文章。今天要分享的是Newtonsoft这个类库对Js......
  • PostgreSQL常用字符串分割函数整理记录
    记录一下postgresql字符串切割处理的函数1.SPLIT_PARTSPLIT_PART()函数通过指定分隔符分割字符串,并返回第N个子串。语法:SPLIT_PART(string,delimiter,position)st......
  • 字符串中的第一个唯一字符
    字符串中的第一个唯一字符一、题目描述给定一个字符串s,找到它的第一个不重复的字符,并返回的所有。如果不存在,则返回-1。示例1输入:s="leetcode"输出:0示例2输......