【字符串】模板

本文深入解析了多种经典字符串算法,包括KMP字符串匹配、Trie树、AC自动机、Manacher算法、回文自动机(PAM)、后缀数组、后缀自动机(SAM)等,每种算法都附有详细的代码实现,为读者提供了丰富的实践案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更新日志

  • 2018/10/4 绝大多数模板
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;

const int N=1000010;

char s1[N],s2[N];
int nxt[N];
int len1,len2;

void getnxt()
{
    for(int i=1,j=0;i<len2;i++)
    {
        while(s2[i]!=s2[j]&&j) j=nxt[j];
        if(s2[i]==s2[j]) nxt[i+1]=++j;
        else nxt[i+1]=0;
    }
    return;
}

int main()
{
    scanf("%s",s1);
    scanf("%s",s2);
    len1=strlen(s1);
    len2=strlen(s2);
    getnxt();
    
    for(int i=0,j=0;i<len1;i++)
    {
        while(s1[i]!=s2[j]&&j) j=nxt[j];
        if(s1[i]==s2[j]) j++;
        if(j==len2) printf("%d\n",i+2-len2);
    }
    
    for(int i=1;i<=len2;i++) printf("%d ",nxt[i]);
    return 0;
}
KMP字符串匹配
struct Trie
{
    int nxt[26];
    bool st;
    bool jud;
}T[500010];

char s[51];
int n,m,cnt=1;

namespace Trie_Tree
{
    void insert()
    {
        int rt=1;
        for(int i=0;s[i];i++)
        {
            int tmp=s[i]-'a';
            if(!T[rt].nxt[tmp])
            T[rt].nxt[tmp]=++cnt;
            rt=T[rt].nxt[tmp];
        }
        T[rt].jud=true;
        return;
    }
    
    int search()
    {
        int rt=1;
        for(int i=0;s[i];i++)
        {
            int tmp=s[i]-'a';
            if(!T[rt].nxt[tmp]) return 0;
            rt=T[rt].nxt[tmp];
        }
        if(!T[rt].jud) return 0;
        if(T[rt].st) return 2;
        T[rt].st=true; return 1;
    }
}
using namespace Trie_Tree;
Trie树
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;

const int N=1000010;

int n,len;
char s[N];

struct Trie
{
    int fail;
    int cnt;
    int nxt[26];
}T[N];

int cnt=0;

void insert()
{
    int rt=0;
    for(int i=0;i<len;i++)
    {
        int tmp=s[i]-'a';
        if(!T[rt].nxt[tmp])
        T[rt].nxt[tmp]=++cnt;
        rt=T[rt].nxt[tmp];
    }
    T[rt].cnt++;
    return;
}

void BFS()
{
    queue<int>q;
    for(int i=0;i<26;i++)
    {
        if(T[0].nxt[i])
        {
            T[T[0].nxt[i]].fail=0;
            q.push(T[0].nxt[i]);
        }
    }
    while(!q.empty())
    {
        int cur=q.front();
        q.pop();
        for(int i=0;i<26;i++)
        {
            if(T[cur].nxt[i])
            {
                T[T[cur].nxt[i]].fail=T[T[cur].fail].nxt[i];
                q.push(T[cur].nxt[i]);
            }
            else
            T[cur].nxt[i]=T[T[cur].fail].nxt[i];
        }
    }
}

int query()
{
    int rt=0,ans=0;
    for(int i=0;i<len;i++)
    {
        int tmp=s[i]-'a';
        rt=T[rt].nxt[tmp];
        for(int j=rt;j&&T[j].cnt!=-1;j=T[j].fail)
        {
            ans+=T[j].cnt;
            T[j].cnt=-1;
        }
    }
    return ans;
}

int main()
{
    scanf("%d",&n);
    while(n--)
    {
        scanf("%s",s);
        len=strlen(s);
        insert();
    }
    T[0].fail=0;
    BFS();
    scanf("%s",s);
    len=strlen(s);
    printf("%d\n",query());
    return 0;
}
AC自动机
#include<bits/stdc++.h>
#define N 51000010
using namespace std;

int len,p[N],ans=1;
char a[N],s[N<<1];

void manacher()
{
    int maxright=0,mid;
    for(int i=1;i<len;i++)
    {
        if(i<maxright)
        p[i]=min(p[mid]+mid-i,p[mid*2-i]);
        else p[i]=1;
        for(;s[i+p[i]]==s[i-p[i]];p[i]++);
        if(p[i]+i>maxright)
        {
            mid=i;
            maxright=mid+p[i];
        }
    }
}

void string_init()
{
    s[0]=s[1]='#';
    for(int i=0;i<len;i++)
    {
        s[i*2+2]=a[i];
        s[i*2+3]='#';
    }
    len=len*2+2;
    s[len]=0;
}

int main()
{
    scanf("%s",a);
    len=strlen(a);
    string_init();
    manacher();
    for(int i=0;i<len;i++)
    ans=max(ans,p[i]);
    ans--;
    printf("%d\n",ans);
    return 0;
}
Manacher算法
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;

const int N=300010;
long long ans;
int len,p,cnt=1;
char s[N];

namespace PAM
{
    struct node
    {
        int nxt[26];
        int fa,len,cnt;
    }T[N];
    
    void Extend(int x)
    {
        int tmp=s[x]-'a';
        while(s[x]!=s[x-T[p].len-1]) p=T[p].fa;
        if(!T[p].nxt[tmp])
        {
            int k=T[p].fa;
            T[++cnt].len=T[p].len+2;
            while(s[x]!=s[x-T[k].len-1]) k=T[k].fa;
            T[cnt].fa=T[k].nxt[tmp];
            T[p].nxt[tmp]=cnt;
        }
        p=T[p].nxt[tmp];
        T[p].cnt++;
    }
}
using namespace PAM;

int main()
{
    scanf("%s",s+1);
    len=strlen(s+1);
    T[0].fa=1;
    T[1].fa=1;
    T[0].len=0;
    T[1].len=-1;
    for (int i=1;i<=len;i++) Extend(i);
    for (int i=cnt;i>1;i--)
    {
        long long tmp=1LL*T[i].cnt*T[i].len;
        if(tmp>ans) ans=tmp;
        T[T[i].fa].cnt+=T[i].cnt;
    }
    return printf("%lld\n",ans),0;
}
回文自动机(PAM)
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;

const int N=1000010;
int SA[N],rank[N],height[N];
int x[N],y[N],bin[N];
int n,m=128;
char s[N];

void getSA()
{
    for(int i=1;i<=n;i++) bin[x[i]=s[i]-'0'+1]++;
    for(int i=1;i<=m;i++) bin[i]+=bin[i-1];
    for(int i=n;i>=1;i--) SA[bin[x[i]]--]=i;
    for(int k=1;k<=n;k<<=1)
    {
        int tmp=0;
        for(int i=n-k+1;i<=n;i++) y[++tmp]=i;
        for(int i=1;i<=n;i++) if(SA[i]>=k+1) y[++tmp]=SA[i]-k;
        for(int i=1;i<=m;i++) bin[i]=0;
        for(int i=1;i<=n;i++) bin[x[y[i]]]++;
        for(int i=1;i<=m;i++) bin[i]+=bin[i-1];
        for(int i=n;i>=1;i--) SA[bin[x[y[i]]]--]=y[i];
        swap(x,y);
        tmp=0;
        for(int i=1;i<=n;i++)
        {
            if(y[SA[i]]!=y[SA[i-1]]) x[SA[i]]=++tmp;
            else if(y[SA[i]+k]!=y[SA[i-1]+k]) x[SA[i]]=++tmp;
            else x[SA[i]]=tmp;
        }
        if(tmp>=n) break;
        m=tmp;
    }
    for(int i=1;i<=n;i++) rank[SA[i]]=i;
    for(int i=1,tmp=0;i<=n;i++)
    {
        if(tmp) --tmp;
        while(s[i+tmp]==s[SA[rank[i]-1]+tmp]) ++tmp;
        height[rank[i]]=tmp;
    }
}

int main()
{
    scanf("%s",s+1);
    n=strlen(s+1);
    getSA();
    for(int i=1;i<=n;i++) printf("%d ",SA[i]);
    return puts(""),0;
}
后缀数组
// luogu-judger-enable-o2
#include<bits/stdc++.h>
using namespace std;

const int MAXN=2000010;

long long ans=0;
char s[MAXN];
int a[MAXN],c[MAXN];
int len,size[MAXN];
int cnt=1,last=1;

struct SAM_node
{
    int nxt[26];
    int fa,len;
}T[MAXN<<1];

namespace SAM
{
    void insert(int x)
    {
        int cur=last,np=++cnt;
        last=np;
        T[np].len=T[cur].len+1;
        for(;cur&&!T[cur].nxt[x];cur=T[cur].fa)
        {
            T[cur].nxt[x]=np;
        }
        if(!cur)
        {
            T[np].fa=1;
        }
        else
        {
            int q=T[cur].nxt[x];
            if(T[cur].len+1==T[q].len)
            {
                T[np].fa=q;
            }
            else
            {
                int nq=++cnt;
                T[nq].len=T[cur].len+1;
                memcpy(T[nq].nxt,T[q].nxt,sizeof(T[q].nxt));
                T[nq].fa=T[q].fa;
                T[q].fa=T[np].fa=nq;
                for(;T[cur].nxt[x]==q;cur=T[cur].fa)
                {
                    T[cur].nxt[x]=nq;
                }
            }
        }
        size[np]=1;
    }
    
    void calc()
    {
        for(int i=1;i<=cnt;i++)
        {
            c[T[i].len]++;
        }
        for(int i=1;i<=cnt;i++)
        {
            c[i]+=c[i-1];
        }
        for(int i=1;i<=cnt;i++)
        {
            a[c[T[i].len]--]=i;
        }
        for(int i=cnt;i;i--)
        {
            int cur=a[i];
            size[T[cur].fa]+=size[cur];
            if(size[cur]>1)
            {
                ans=max(ans,1LL*size[cur]*T[cur].len);
            }
        }
        printf("%lld\n",ans);
        return;
    }
}
using namespace SAM;

int main()
{
    scanf("%s",s+1);
    len=strlen(s+1);
    for(int i=1;i<=len;i++)
    insert(s[i]-'a');
    calc();
    return 0;
}
后缀自动机(SAM)
int getmin()
{
    int i=0,j=1,k=0,t;
    while(i<len && j<len && k<len)
    {
        t=s[(i+k)%len]-s[(j+k)%len];
        if (!t) k++;
        else
        {
            if (t>0) i+=k+1; 
            else j+=k+1;
            if (i==j) j++;
            k=0;
        }
    }
    return min(i,j);
}
最小表示法
unsigned long long hash()
{
    int len=strlen(s);
    unsigned long long ans=0;
    for (int i=0;i<len;i++)
        ans=(ans*base+(unsigned long long)s[i])%mod;
    return ans;
}
哈希(Hash)

 

转载于:https://www.cnblogs.com/SaltedHXJ/p/9741555.html

内容概要:本文详细介绍了扫描单分子定位显微镜(scanSMLM)技术及其在三维超分辨体积成像中的应用。scanSMLM通过电调透镜(ETL)实现快速轴向扫描,结合4f检测系统将不同焦平面的荧光信号聚焦到固定成像面,从而实现快速、大视场的三维超分辨成像。文章不仅涵盖了系统硬件的设计与实现,还提供了详细的软件代码实现,包括ETL控制、3D样本模拟、体积扫描、单分子定位、3D重建和分子聚类分析等功能。此外,文章还比较了循环扫描与常规扫描模式,展示了前者在光漂白效应上的优势,并通过荧光珠校准、肌动蛋白丝、线粒体网络和流感A病毒血凝素(HA)蛋白聚类的三维成像实验,验证了系统的性能和应用潜力。最后,文章深入探讨了HA蛋白聚类与病毒感染的关系,模拟了24小时内HA聚类的动态变化,提供了从分子到细胞尺度的多尺度分析能力。 适合人群:具备生物学、物理学或工程学背景,对超分辨显微成像技术感兴趣的科研人员,尤其是从事细胞生物学、病毒学或光学成像研究的科学家和技术人员。 使用场景及目标:①理解和掌握scanSMLM技术的工作原理及其在三维超分辨成像中的应用;②学习如何通过Python代码实现完整的scanSMLM系统,包括硬件控制、图像采集、3D重建和数据分析;③应用于单分子水平研究细胞内结构和动态过程,如病毒入侵机制、蛋白质聚类等。 其他说明:本文提供的代码不仅实现了scanSMLM系统的完整工作流程,还涵盖了多种超分辨成像技术的模拟和比较,如STED、GSDIM等。此外,文章还强调了系统在硬件改动小、成像速度快等方面的优势,为研究人员提供了从理论到实践的全面指导。
内容概要:本文详细介绍了基于Seggiani提出的渣层计算模型,针对Prenflo气流床气化炉中炉渣的积累和流动进行了模拟。模型不仅集成了三维代码以提供气化炉内部的温度和浓度分布,还探讨了操作条件变化对炉渣行为的影响。文章通过Python代码实现了模型的核心功能,包括炉渣粘度模型、流动速率计算、厚度更新、与三维模型的集成以及可视化展示。此外,还扩展了模型以考虑炉渣组成对特性的影响,并引入了Bingham流体模型,更精确地描述了含未溶解颗粒的熔渣流动。最后,通过实例展示了氧气-蒸汽流量增加2%时的动态响应,分析了温度、流动特性和渣层分布的变化。 适合人群:从事煤气化技术研究的专业人士、化工过程模拟工程师、以及对工业气化炉操作优化感兴趣的科研人员。 使用场景及目标:①评估不同操作条件下气化炉内炉渣的行为变化;②预测并优化气化炉的操作参数(如温度、氧煤比等),以防止炉渣堵塞;③为工业气化炉的设计和操作提供理论支持和技术指导。 其他说明:该模型的实现基于理论公式和经验数据,为确保模型准确性,实际应用中需要根据具体气化炉的数据进行参数校准。模型还考虑了多个物理场的耦合,包括质量、动量和能量守恒方程,能够模拟不同操作条件下的渣层演变。此外,提供了稳态求解器和动态模拟工具,可用于扰动测试和工业应用案例分析。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值