NOIP考纲 字符串&排序

字符串:
1.kmp

var
    p:array[1..1000] of longint;
    i,j,k,n,m,ans:longint;
    s,t:string;
begin
    readln(s);
    readln(t);
    n:=length(s);
    m:=length(t);
    p[1]:=0;
    j:=0;
    for i:=2 to m do
    begin
        while (j<>0) and (t[j+1]<>t[i]) do j:=p[j];
        if t[j+1]=t[i] then j:=j+1;
        p[i]:=j;
    end;

    ans:=0;
    j:=0;
    for i:=1 to n do
    begin
        while (j>0) and (s[i]<>t[j+1]) do j:=p[j];
        if s[i]=t[j+1] then inc(j);
        if j=m then begin inc(ans);j:=p[m];end;
    end;
    writeln(ans);
end.

2.nlogn lis

var
        i,j,k,o,p,n,m:longint;
        l,r,x:longint;
        f:array[0..27000]of longint;
begin
        assign(input,'love.in');
        assign(output,'love.out');
        reset(input);
        rewrite(output);
        read(n);
        for i:=1 to n do
        begin
                read(x);
                l:=1;
                r:=f[0];
                while l<r do
                begin
                        m:=(l+r)div 2;
                        if f[m]<=x then l:=m+1 else r:=m;
                end;
                if (l>=r)and(f[f[0]]<=x)then
                begin
                        inc(f[0]);
                        f[f[0]]:=x;
                        l:=f[0];
                end
                else if x<f[l] then f[l]:=x;
        end;
        writeln(f[0]);
end.

3.nlogn lcs(数据结构求lis)

#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;
const int N=300007;
int i,n,m,len,ans;
int b[N],a[N],pos[N],lis[N],tree[N*4];

inline void make(int x,int l,int r,int l1,int r1)
{
    if (l==r)
    {   tree[x]=r1;return;}
    int mid=(l+r)/2;
    if (l1<=mid)make(x*2,l,mid,l1,r1);
    else make(x*2+1,mid+1,r,l1,r1);
    tree[x]=max(tree[x*2],tree[x*2+1]);
}
inline void find(int x,int l,int r,int l1,int r1)
{
    if (l==l1 && r==r1)
    {
        ans=max(ans,tree[x]);
        return;
    }
    int mid=(l+r)/2;
    if (r1<=mid)find(x*2,l,mid,l1,r1);
    else if(l1>mid)find(x*2+1,mid+1,r,l1,r1);
    else 
    {
        find(x*2,l,mid,l1,mid);
        find(x*2+1,mid+1,r,mid+1,r1);
    }
}
int main()
{

  scanf("%d%d",&n,&m);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);

    }
    for (i=1;i<=m;i++)
    {
        scanf("%d",&b[i]);

    }
    for (i=1;i<=n;i++) pos[a[i]]=i;
    for (i=1;i<=m;i++) b[i]=pos[b[i]];

    for (i=1;i<=m;i++)
    {
        ans=0;
        if (b[i])
        find(1,0,m,0,b[i]-1);
        else continue;
        ans++;
        lis[i]=ans;
        make(1,0,m,b[i],lis[i]);
        len=max(len,lis[i]);
    }

    printf("%d\n",len);
    return 0;
}

排序
1.归并

var
    a,b:array[1..10000] of longint;
    i,j,k,n,m:longint;
procedure merge(l,r:longint);
    var
        i,j,mid,t,x,y:longint;
    begin
        if l=r then exit;
        mid:=(l+r) div 2;
        merge(l,mid);
        merge(mid+1,r);

        fillchar(b,sizeof(b),0);
        x:=l;y:=mid+1;
        for i:=l to r do
            if ((x<=mid) and (y<=r) and (a[x]<a[y])) or (y>r) then
            begin
                b[i]:=a[x];
                inc(x);
            end
            else
            begin
                b[i]:=a[y];
                inc(y);
            end;

        for i:=l to r do a[i]:=b[i];
    end;
begin
    readln(n);
    for i:=1 to n do read(a[i]);
    merge(1,n);
    for i:=1 to n do write(a[i],' ');
    writeln;
end.

求逆序对
①归并:上面那个标,当a[i]>a[j]的时候ans+=mid-i+1就行了。
②树状数组:

#include <iostream>  
using namespace std;  

#define  N  10  

struct Node{  
    int data;  
    int pos;  
};  

Node d[N+1];  
int inverse[N+1];   
int count[N];   

int cmp(const void*a,const void*b)  
{  
    Node *pa=(Node*)a;  
    Node *pb=(Node*)b;  
    return pa->data-pb->data;  
}  

int lowbit(int t){   
    return t & (t^(t-1));   
}  
void modify(int pos,int num)  
{  
    while (pos<=N) {  
        inverse[pos]+=num;  
        pos+=lowbit(pos);  
    }  
}  
int sum(int end)  
{  
    int sum=0;  
    while (end>0) {  
        sum+=inverse[end];  
        end-=lowbit(end);  
    }  
    return sum;  
}  


int main()  
{  
    memset(inverse,0,sizeof(inverse)); //初始化  
    memset(count,0,sizeof(count));  

    char* a="9854623870";  //长度N  
    for(int i=0;i<strlen(a);i++)  
    {  
        d[i+1].data =a[i]-'0';  
        d[i+1].pos=i+1;  
    }  

    qsort(d+1,N,sizeof(Node),cmp);  

    int id=1;  
    count[d[1].pos]=1;  
    for(int i=2;i<=N;i++)  
    {  
        if(d[i].data==d[i-1].data)  
            count[d[i].pos]=id;  
        else  
            count[d[i].pos]=++id;  
    }  
    int num=0;  
    for(int i=1;i<=N;i++)  
    {  
        modify(count[i],1);  
        num+=i-sum(count[i]);  
    }  

    cout<<num<<endl;  

    return 0;  
}  
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值