字符串(板子)

STL(字符串)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 3e6+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
int main()
{
    string st1("babbabab");
    string st2("aabcbcabcbabcc");
    string str1 = "abc";
    ///查找字符串:
    ///find-从指定位置起向后查找,直到串尾

///1.默认从位置0(即第1个字符)开始查找
    cout << st1.find('a') << endl;

///2.在st1中,从位置2(b,包括位置2)开始,查找a,返回首次匹配的位置
    cout << st1.find('a', 2) << endl;


///3.从st2的位置2(b)开始匹配,返回第一次成功匹配时匹配的串(abc)的首字符在st2中的位置,失败返回-1
    cout << st2.find(str1, 2) << endl;

///4.取abcdefg得前3个字符(abc)参与匹配,相当于st2.find("abc", 2)
    cout << st2.find("abcdefg", 2, 3) << endl;

    ///删除字符串
    cout<<st2.erase(1,2)<<endl;

    ///反转字符串
    reverse(str1.begin(), str1.end());
    cout<<str1<<endl;

    ///截取子串
    cout<<st1.substr(2,5)<<endl;
    cout<<st1.substr(2)<<endl;
    cout<<st1.substr()<<endl;

    ///交换字符串
    swap(st1,st2);
    cout<<st1<<endl;
    st1.swap(st2);
    cout<<st1<<endl;

    ///比较字符串
    ///int compare(const char *s) const;
    ///int compare(int pos, int n,const char *s) const;
    ///int compare(int pos, int n,const char *s, int pos2) const;
    ///int compare(int pos, int n,const string &s,int pos2=0,int n2=posn2)const;
    ///比较当前字符串从pos开始的n个字符组成的字符串与s中pos2开始的n2个字符组成的字符串的大小
    ///compare函数在>时返回1,<时返回-1,==时返回0
    cout<<st1.compare(1,2,st2)<<endl;
    cout<<st1.compare(1,2,st2,4,2)<<endl;
}

tire树

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 4e6+10;
const ll int N = 1e5+10;
#define bug(x) cout<<#x<<"=="<<x<<endl;
string a;
int tree[maxn*4][30]={0};
int way1[maxn*4] = { 0 };
int way2[maxn*4] = { 0 };
///操作各种各样,在建树的时候修改即可
int tot=0;
void add(string a)
{ji
    int h=0;
    for(int i=0;i<a.length();i++)
    {
        int id=a[i]-'a';
        if(!tree[h][i])
        {
            tot++;
            tree[h][i] = tot;
        }
        h = tree[h][i];
        way2[h]++;
        ///记录每一个单词的前缀字符串数目
    }
    way2[h]++;///记录每一个单词的数量
}
int main()
{
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>a;
        add(a);
    }
}

AC自动机

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 4e6+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<"=="<<x<<endl;
struct AC_automaton
{
    int tr[N][26],cnt;///tire
    int e[N];///该单词出现次数
    int fail[N];
    void add(char s[])
    {
        int p=0;
        for(int i=0; s[i]; i++)
        {
            int k = s[i]-'a';
            if(!tr[p][k])cnt++,tr[p][k]=cnt;
            p = tr[p][k];
        }
        e[p]++;
    }
    void build()
    {
        queue<int> q;
         memset(fail,0,sizeof(fail));
        for(int i=0; i<26; i++)if(tr[0][i])q.push(tr[0][i]);
        while(!q.empty())
        {
            int k=q.front();
            q.pop();
            for(int i=0;i<26;i++)
            {
                if(tr[k][i])
                {
                    fail[ tr[k][i] ] = tr[ fail[k] ][i];
                      q.push( tr[k][i] );
                }
                else
                {
                    tr[k][i] = tr[ fail[k] ][i];
                }
            }
        }
    }
    int query(char *s)
    {
        int p=0;
        int res=0;
        for(int i=0;s[i];i++)///枚举这个单词的所有前缀 在前面的树里有没有出现过
        {
            int k = s[i]-'a';
            p = tr[p][k];
            for(int j=p;j&&~e[j];j=fail[j])
            {
                ///判断e[j]是不是为-1
                res += e[j];
                e[j] = -1;
            }
        }
        return res;
    }
};
AC_automaton a;
char b[maxn];
int main()
{
    int n;
    cin>>n;
    for(int i=1; i<=n; i++)
    {
        getchar();
        cin>>b;
        a.add(b);

    }
    a.build();
    getchar();
    cin>>b;
    cout<<a.query(b)<<endl;
}

KMP

string a;
int nextt[maxn] = { -1 };
///表示了字符串1~i最大前缀长度
int main()
{
    cin>>a;
    nextt[0] = -1;
    int j=0;
    ///当前参与匹配的字符串为1~j;
    int k=-1;///当前正在匹配的字符串前缀位置
    while(j<a.length())
    {
        if(k==-1||a[k]==a[j])
        {
            ///当k等于的0的时候 说明一直回溯到了字符串最前端,前面都没有匹配的
            ///所以next[j] = 0;
            ///当A[j]和a[k]匹配的时候,说明next[j+1]前的最大前缀和后缀相同长度为k;
            k++;
            j++;
            nextt[j] = k;
        }
        else
        {
            k = nextt[k];
            ///当前位置不行,就跳转到上一个
        }
    }
}

kuangbin kmp

(HDU)Number Sequence

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 3e6+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
int a[maxn] = { 0 };
int nextt[maxn] = { 0 };
int b[maxn] = { 0 };
int n,m;
void get_kmp()
{
    memset(nextt,0,sizeof(nextt));
    nextt[0] = -1;
    int i=-1;
    int j=0;
    while(j<m)
    {
        if( i==-1 || a[i]==a[j] )
        {
            j++;
            i++;
            nextt[j]=i;

        }
        else
        {
           i=nextt[i];
        }
    }
}
int get_same()
{
    int ans = 0;
    int i=0;
    int j=0;
    while(j<m&&i<n)
    {
        if(j==-1||b[i]==a[j])
        {
            i++;
            j++;
        }
        else
        {
            j=nextt[j];
        }
    }
    if(j==m)
    {
        return i-j+1;
    }
    else
    {
        return -1;
    }
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {

        scanf("%d %d",&n,&m);
        for(int i=0;i<n;i++)
        {
            scanf("%d",&b[i]);
        }
        for(int i=0;i<m;i++)
        {
            scanf("%d",&a[i]);///a为模式串
        }

        if(m>n)
        {
            printf("-1\n");
            continue;
        }
        get_kmp();
        cout<<get_same()<<'\n';
    }
}

(dp+kmp)Count the string

不重合的字符串kmp

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 2e5+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
typedef pair<int,int> pp;
char zmb[maxn] = { 0 };
char fm[maxn] = { 0 };
char s[maxn] = { 0 };
int nextt[maxn] = { 0 };
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%s",zmb);
        scanf("%s",s);
        nextt[0] = -1;
        int i=-1;
        int j=0;
        int len=strlen(s);
        while(j<len)
        {
            if(i==-1||s[i]==zmb[ s[j]-'a' ])
            {
                i++;
                j++;
                nextt[j] = i;
            }
            else
            {
                i = nextt[i];
            }
        }
        int now=len;
        while(nextt[now]*2>len)
        {
            now=nextt[now];
        }
        for(int i=0; i<26; i++)
        {
            fm[ zmb[i]-'a' ]=i+'a';
        }
        printf("%s",s);
        for(int i=nextt[now]; i<len-nextt[now]; i++)
        {
            printf("%c",fm[ s[i]-'a' ]);
        }
        printf("\n");
    }
}

马拉车算法(字符串+动态规划)

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 3e7+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
int p[maxn] = { 0 };
///以i为中心的最大回文字符串(此时的字符串是处理过的)到左端点的距离 + 1
int id=0;///当前计算的最大长度的字符串的中心
int maxx=0;///以id为中心的最大回文字符串(此时的字符串是处理过的)的右端点+1
int main()
{
    string a;
    string b;
    cin>>a;
    b += '$';
    for(int i=0;i<a.size();i++)
    {
        b += '#';
        b += a[i];
    }
    b += '#';
    int len=b.length();
    ///预处理,将每一个字符串变成奇数串 使子串的中心固定
    int ans=0;
    for(int i=1;i<len;i++)
    {
        if(maxx>i)
        {
            p[i] = min(maxx-i,p[2*id-i]);
            ///当maxx>i的时候 说明 以id为中心,左右两端长度为maxx-id的字符串里面包含了b[i];
            ///说明 id-(i-id)和b[i]是这个字符串里面两个对称点,
            ///而且i-(i-maxx)~maxx部分也和2*id-maxx~2*id-i+(i-maxx)相同
            ///所以如果p[2*id-1]<=maxx-i -> p[i]==p[2*id-1];
            ///如果p[2*id-1]>maxx-i,只能截取肯定相同的部分即maxx-i;
        }
        else
        {
            p[i] = 1;
        }
        while(b[ i-p[i] ] ==b[ i+p[i] ] )
        {
            p[i]++;
        }
        if(i+p[i]>maxx)
        {
            maxx = i + p[i];
            id = i;
        }
        ans=max(p[i]-1,ans);
    }
    printf("%d\n",ans);
}

后缀数组

后缀排序

洛谷模板题

#include <bits/stdc++.h>
using namespace std;
#define ll long long
const ll int maxn = 3e6+10;
const ll int N = 4e6+10;
#define bug(x) cout<<#x<<" == "<<x<<endl;
int rankk[maxn] = { 0 };
int tmp[maxn] = { 0 };
int sa[maxn] = { 0 };
int ans[maxn] = { 0 };
string a;
int k = 0;
int n;
bool cmp(int i,int j)
{
    if(rankk[i] != rankk[j])
    {
        return rankk[i]<rankk[j];
    }
    else
    {
        int ri = i+k<=n ? rankk[i+k]:-1;
        int rj = j+k<=n ? rankk[j+k]:-1;
        return ri < rj;
    }
}
int main()
{
    cin>>a;
    n = a.length();
    for(int i=0; i<n; i++)
    {
        sa[i] = i;
        rankk[i] = a[i];
    }
    sa[n] = n;
    rankk[n] = -1;
    for(k=1; k<=n; k*=2)
    {
        sort(sa,sa+1+n,cmp);
        tmp[sa[0]] = 0;
        for (int i=1; i <= n; i++)
            tmp [sa[i]] = tmp[sa [i - 1]] + (cmp(sa[i-1],sa[i])?1 :0);

        for(int i=0; i<=n; i++)
        {
            rankk[i]=tmp[i];
        }
    }
    for(int i=0;i<n;i++)
    {
        ans[ tmp[i] ]= i+1;
    }
    for(int i=1;i<=n;i++)
    {
        printf("%d ",ans[i]);
    }
    printf("\n");
}

基于后缀数组的字符串匹配

bool contain(string s)
{
    int l=0,r=a.length();
    int ans=0;
    while(l<=r)
    {
        int mid=(l+r)/2;
        if(a.compare(sa[mid],s.length(),s)<=0)
        {
            ans = mid;
            l = mid+1;
        }
        else
        {
            r = mid-1;
        }
    }
    return a.compare(sa[ans],s.length(),s)==0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值