zoukankan      html  css  js  c++  java
  • 字符串-----KMP竟然是18禁

    今天学了一下午字符串,讲到结束也没讲KMP。有人问老师为什么不讲,老师来一句:字符串noip不考,而且还是18禁,自然不讲。【手动滑稽】

    所以我也不讲。【微笑】

    1.表达式树

    表示3+5*8

    最后计算的符号是根节点,是一课二叉树,左右子树可以是数或式。

    例题:表达式计算

    代码如下

    /*
    10+(2+3)*4
    30
    */
    
    #include <iostream>
    #include <stack>
    #include <cstring>
    using namespace std;
    
    const int MAXN = 10000 + 10;
    char str[MAXN];
    
    int solve(int l, int r) // 璁$畻杈撳叆鐨勮〃杈惧紡[l,r]鍐呯殑鍊?
    {
        // 鎵炬渶鍚庝竴涓��绠楃殑浣嶇疆
        int pos=-1;
        int flag=0;
        int level=2; // 0:+- 1:*/
        for(int i=l;i<=r;i++)
        {
            if(str[i]=='(')flag++;
            if(str[i]==')')flag--;
            if(flag == 0 && (str[i]=='+'||str[i]=='-'||str[i]=='*'||str[i]=='/'))
            {
                int l=-1;
                switch(str[i])
                {
                    case '+':case '-':l=0;break;
                    case '*':case '/':l=1;break;
                }
                if(level >= l)
                {
                    level=l;
                    pos=i;
                }
            }
        }
        if(pos==-1)
        {
            if(str[l]=='('&&str[r]==')') return solve(l+1,r-1);
            int x=0;
            for(int i=l;i<=r;i++)
                x=x*10+str[i]-'0';
            return x;
        }
        int a = solve(l, pos-1);
        int b = solve(pos+1, r);
        int ans;
        switch(str[pos])
        {
            case '+':ans=a+b;break;
            case '-':ans=a-b;break;
            case '*':ans=a*b;break;
            case '/':ans=a/b;break; // 3*2/3
        }
        return ans;
    }
    int main()
    {
        cin >> (str+1);
        cout << solve(1, strlen(str+1)) << endl;
    
        return 0;
    }

    这道题还有一个栈的做法

    代码如下

    /*
    1+(2+3)*4
    21
    */
    // 鍋囪�杈撳叆鐨勬暟瀛楀湪[0,9]
    
    #include <iostream>
    #include <stack>
    using namespace std;
    
    const int MAXN = 10000 + 10;
    char str[MAXN];
    stack<int> nums;
    stack<char> symbol;
    
    void pop()
    {
        int a = nums.top();nums.pop();
        int b = nums.top();nums.pop();
        char s = symbol.top();symbol.pop();
        int ans;
        switch(s)
        {
            case '+':ans=a+b;break;
            case '-':ans=b-a;break;
            case '*':ans=a*b;break;
            case '/':ans=b/a;break; // 3*2/3
        }
        nums.push(ans);
    }
    int main()
    {
        cin >> (str+1);
        for(int i=1;str[i]!=0;i++)
        {
            char c=str[i];
            if('0'<=c&&c<='9')
            {
                nums.push(c-'0');
            } else {
                if(c==')')
                {
                    while(symbol.top() != '(') pop();
                    symbol.pop();
                } else if (c=='+' || c=='-')
                {
                    while(!symbol.empty()
                        &&symbol.top()!='+'
                        &&symbol.top()!='-'
                        &&symbol.top()!='(') pop();
                    symbol.push(c);
                } else symbol.push(c);
            }
        }
        while(!symbol.empty())pop();
        cout<<nums.top()<<endl;
    
        return 0;
    }

    2.hash(搞一个233进制数)&&trie树

    例题:字符串统计

    const int P = 673, MOD = 1000007;
    
    int hash(char* str)
    // 瑕佹眰鐩稿悓瀛楃�涓茶繑鍥炵殑瀛楃�涓插繀椤荤浉鍚?
    // 涓嶅悓鐨勫瓧绗︿覆杩斿洖鍊煎敖閲忎笉鍚?
    {
        int ans=0;
        for(int i=0;str[i];i++)
            ans=(ans*P+str[i])%MOD;
        return ans;
    }
    vector<string> L[MOD];
    int main()
    {
        int n;
        cin >> n;
        char str[100 + 10];
        while(n--)
        {
            cin>>str;
            int h=hash(str);
            bool same=false;
            for(int i=0;i<(int)L[h].size()&&!same;i++)
                if(str==L[h][i])
                    same=true;
            puts(same ? "YES" : "NO");
            if(!same) L[h].push_back(str);
        }
    }
    /*hash*/
    const int MAXN = 100000 + 10;
    
    struct Node
    {
        int son[26];
        int mark;
    };
    Node tree[MAXN*10];
    int root=0, op=0;
    
    bool insert(char* str) // 鎻掑叆瀛楃�涓诧紝杩斿洖璇ュ瓧绗︿覆鏄�惁宸茬粡鍑虹幇杩?
    {
        int pos=root;
        for(int i=0;str[i];i++)
        {
            int c=str[i]-'a';
            if(tree[pos].son[c] == 0) tree[pos].son[c] = ++op;
            pos = tree[pos].son[c];
        }
        int mark=tree[pos].mark;
        tree[pos].mark=1;
        return mark!=0;
    }
    int main()
    {
        int n;
        cin >> n;
        char str[100 + 10];
        while(n--)
        {
            cin>>str;
            puts(insert(str) ? "YES" : "NO");
        }
    }
    /*trie树*/

    例题:情书

    const int MAXN = 100000 + 10;
    
    struct Node
    {
        int son[26];
        int mark;
        int time; // 琛ㄧず鏈€鏂板尮閰嶇殑鏄�摢鍙ヨ瘽
    };
    Node tree[MAXN*10];
    int root=0, op=0;
    char str[1000000 + 10];
    int cnt, ans;
    // cnt琛ㄧず褰撳墠姝e湪澶勭悊鐨勫崟璇嶆槸绗�嚑鍙ヨ瘽
    
    void insert(char* str) // 鎻掑叆瀛楃�涓?
    {
        int pos=root;
        for(int i=0;str[i];i++)
        {
            int c=str[i]-'a';
            if(tree[pos].son[c] == 0) tree[pos].son[c] = ++op;
            pos = tree[pos].son[c];
        }
        tree[pos].mark=1;
    }
    void search(char* str)
    {
        int pos=root;
        for(int i=0;str[i];i++)
        {
            int c=str[i]-'a';
            if(tree[pos].son[c] == 0) return;
            pos = tree[pos].son[c];
        }
        if(tree[pos].mark==1 && tree[pos].time!=cnt)
            ans++;
        tree[pos].time=cnt;
    }
    int main()
    {
        int n;
        cin >> n;
        while(n--)
        {
            cin>>str;
            insert(str);
        }
        cnt=1;
        while(cin>>str)
        {
            int len=strlen(str);
            bool juzi=false;
            if(str[len-1]=='.')
            {
                juzi=true;
                str[len-1]='';
            }
            search(str);
            if(juzi)
            {
                cout<<ans<<endl;
                ans=0;
                cnt++;
            }
        }
    }

    例题:LCP(最长公共前缀hash做法)

    const int P = 637, MOD = 1000000007;
    char str[MAXN];
    long long H[MAXN];
    long long POW[MAXN];
    
    int main()
    {
        cin>>str+1;
        n=strlen(str+1);
        for(int i=1;i<=n;i++)
            H[i]=(H[i-1]*P+str[i])%MOD;
        POW[0]=1;
        for(int i=1;i<=n;i++)
            POW[i]=(POW[i-1]*P)%MOD;
        int A, B;
        while(cin>>A>>B)
        {
            int l=0, r=min(n-A+1, n-B+1), mid;
            while(l<r)
            {
                mid=(l+r)/2+1; // l=0, r=1 [0, 1]/[-1, 0]
                // h1涓簊tr[A~A+mid-1]鐨刪ash鍊?
                long long h1=((H[A+mid-1]-H[A-1]*POW[mid])%MOD+MOD)%MOD;
                long long h2=((H[B+mid-1]-H[B-1]*POW[mid])%MOD+MOD)%MOD;
                if(h1==h2)l=mid;
                else r=mid-1;
            }
        }
    }
    
    // -9 % 4 = (-1 + 4) % 4 = 3
  • 相关阅读:
    Arduino101学习笔记(十三)—— 101六轴传感器
    Arduino101学习笔记(十二)—— 101定时器中断
    Arduino101学习笔记(十一)—— 蓝牙BLE
    Arduino101学习笔记(十)—— 串口通信
    Arduino101学习笔记(九)—— 中断函数
    Arduino101学习笔记(八)—— 函数库
    Arduino101学习笔记(七)—— 时间API
    [mount]linux 挂载时 mount: wrong fs type, bad option, bad superblock on /dev/sdb
    [sed]字符串替换
    [net]netcat 做网络端口监听
  • 原文地址:https://www.cnblogs.com/ZDHYXZ/p/8432843.html
Copyright © 2011-2022 走看看