字符串2 暑假day6-7(7.26)

字符串2 简单基础知识

KMP

概述:
在长度为n的文本S中,找到某个长度为m的关键词P,类似这种问题的解决。
这两个字符串都是很一般的情况时(寻找字串很复杂时),用到KMP更简便。
一些特殊的情况时,用暴力比较简单。
理解:
通过分析P对P进行预处理,在匹配S的时候能够跳过一些字符串,达到快速匹配。
两个指针i,j: 指向S的指针i不回溯(走到尾),指向P的指针回溯。
核心: Next[]数组,用于指向j回溯的位置。(通过预处理得到)
例题: hdu287
KMP算法的模板有两部分,一getFail()预计算Next[]数组,二kmp()函数实现在S中找P(注意每次匹配的初始位置)

#include <bits/stdc++.h>
using namespace std;
const int maxn=1000+5;
char str[maxn],pattern[maxn];
int Next[maxn];
int cnt;
int getfail(char *p,int plen)
{
    //预计算Next[],失配情况下得到j回溯的位置
    Next[0]=0;Next[1]=0;
    for(int i=0;i<plen;i++)
    {
        int j=Next[i];
        while(j&&p[i]!=p[j]) j=Next[j];
        Next[i+1]=(p[i]==p[j])?j+1:0;
    }
}
int kmp(char *s,char *p)
{
    //在S中找P
    int last=-1;
    int slen=strlen(s),plen=strlen(p);
    getfail(p,plen);//预计算Next[]数组
    int j=0;
    for(int i=0;i<slen;i++)
    {
        while(j&&s[i]!=p[j]) j=Next[j];
        if(s[i]==p[j]) j++;//当前位置字符匹配继续
        if(j==plen)//完全匹配
        {
            //匹配起点i+1-plen,终点i
            //以下是针对本题的解决
            if(i-last>=plen)//判断新的匹配和上一个匹配是否能分开
            {
                cnt++;
                last=i;
            }
        }
    }
}
int main()
{
    while(cin>>str)
    {
        if(str[0]=='#') break;
        cin>>pattern;
        cnt=0;
        kmp(str,pattern);
        cout<<cnt<<endl;
    }
    return 0;
}

AC自动机

KMP是单模拟匹配算法,处理在一个文本串中查找一个模拟串的问题,AC自动机是多模匹配算法,能在一个文本串中同时查找多个不同的模拟串
针对多模拟匹配问题:给定一个长度为n的文本S,以及k个平均长度为m的模拟串,要求搜索这些模拟串的位置。
模板题:hdu2222
(不理解为什么要这样子,对树的结构还是很陌生)

#include <bits/stdc++.h>

using namespace std;
const int maxn=1000000+100;
const int size=26;
const int maxnode=1000000+100;
int n,ans;
bool vis[maxn];
map<string,int>ms;
int ch[maxn][size+5];
int val[maxnode];
int idx(char c)
{
    return c-'a';
}
struct Trie
{
    int sz;
    Trie()
    {
        sz=1;
        memset(ch[0],0,sizeof(ch[0]));
        memset(vis,0,sizeof(vis));//初始化
    }
    void insert(char *s)
    {
        int u=0,n=strlen(s);
        for(int i=0; i<n; i++)
        {
            int c=idx(s[i]);
            if(!ch[u][c])
            {
                memset(ch[sz],0,sizeof(ch[sz]));
                val[sz]=0;
                ch[u][c]=sz++;
            }
            u=ch[u][c];
        }
        val[u]++;
    }
};
//自动机
int last[maxn],f[maxn];
void print(int j)
{
    if(j&&!vis[j])
    {
        ans+=val[j];
        vis[j]=1;
        print(last[j]);
    }
}
int getfail()
{
    queue<int>q;
    f[0]=0;
    for(int c=0; c<size; c++)
    {
        int u=ch[0][c];
        if(u)
        {
            f[u]=0;
            q.push(u);
            last[u]=0;
        }
    }
    while(!q.empty())
    {
        int r=q.front();
        q.pop();
        for(int c=0; c<size; c++)
        {
            int u=ch[r][c];
            if(!u)
            {
                ch[r][c]=ch[f[r]][c];
                continue;
            }
            q.push(u);
            int v=f[r];
            while(v&&!ch[v][c]) v=f[v];
            f[u]=ch[v][c];
            last[u]=val[f[u]]?f[u]:last[f[u]];
        }
    }
}
void find_T(char *T)
{
    int n=strlen(T);
    int j=0;
    for(int i=0;i<n;i++)
    {
        int c=idx(T[i]);
        j=ch[j][c];
        if(val[j]) print(j);
        else if(last[j]) print(last[j]);
    }
}
char tmp[105];
char text[1000000+1000];
int main()
{
    int T;
    cin>>T;
    while(T--)
    {
        cin>>n;
        Trie trie;
        ans=0;
        for(int i=0;i<n;i++)
        {
            cin>>tmp;
            trie.insert(tmp);
        }
        getfail();
        cin>>text;
        find_T(text);
        cout<<ans<<endl;
    }
    return 0;
}

//并记不住,,
//最后一次码代码,,

后缀树和后缀数组

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是求解多元多项式回归的 MATLAB 代码: ```matlab % 输入数据 x1 = [36.4 37.2 37.2 36.2 31.5 28.9 27.2 26.7 26.1 26.1 25.4 25.3 25.4]'; x2 = [50.0 52.0 49.0 51.0 68.0 74.0 83.0 82.0 88.0 88.0 90.0 88.0 87.0]'; x3 = [982.9 982.2 981.8 981.6 982.3 982.6 983.4 983.5 984.0 983.6 984.4 984.5 984.4]'; y = [-7.30 -7.36 -7.35 -7.33 -7.31 -7.30 -7.26 -7.22 -7.21 -7.23 -7.18 -7.17 -7.14]'; % 构建设计矩阵X X = [ones(size(x1)) x1 x2 x3 x1.^2 x1.*x2 x1.*x3 x2.^2 x2.*x3 x3.^2]; % 求解回归系数 beta = X \ y; % 构建预测模型 model = @(x1,x2,x3) beta(1) + beta(2)*x1 + beta(3)*x2 + beta(4)*x3 ... + beta(5)*x1.^2 + beta(6)*x1.*x2 + beta(7)*x1.*x3 ... + beta(8)*x2.^2 + beta(9)*x2.*x3 + beta(10)*x3.^2; % 预测并绘制拟合图 x1fit = min(x1):0.1:max(x1); x2fit = min(x2):0.1:max(x2); x3fit = min(x3):0.1:max(x3); [X1FIT,X2FIT,X3FIT] = meshgrid(x1fit,x2fit,x3fit); YFIT = model(X1FIT,X2FIT,X3FIT); figure; plot3(x1,x2,x3,'o',x1fit,x2fit,x3fit,'*'); hold on; mesh(X1FIT,X2FIT,X3FIT,YFIT); xlabel('x1'); ylabel('x2'); zlabel('x3'); title('拟合图'); % 绘制残差图 YFIT = model(x1,x2,x3); figure; plot(YFIT - y,'o'); xlabel('样本编号'); ylabel('残差'); title('残差图'); ``` 运行上述代码后,会先绘制拟合图,然后绘制残差图。拟合图中,蓝色的点表示原始数据,红色的点表示拟合值,可以看到拟合值与原始数据比较接近;残差图中,横轴表示样本编号,纵轴表示残差,残差的分布应该比较均匀,没有明显的规律。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值