• 用c++后缀自动机实现最大公共字符串算法,并封装成Python库


    后缀自动机的C++代码转自https://e-maxx.ru/algo/suffix_automata,其余封装为自写。

    在C++文件同级目录建立setup.py文件,代码如下:

    # !/usr/bin/env python
    from distutils.core import setup, Extension
    mod = "sam"
    setup(name=mod, ext_modules=[Extension(mod, sources=['sam_lcs.cpp'])])

    封装完后缀自动机的源码后,命令行编译、安装、卸载,安装后即可在Python里import调用:

    python setup.py build
    python setup.py install
    python setup.py uninstall

    包装模块的C++函数编写如下:

    #include <map>
    #include <string>
    #include <Python.h>
    
    using namespace std;
    
    struct state
    {
        int len, link;
        map<char, int> next;
    };
    
    const int MAXLEN = 100000;
    state st[MAXLEN * 2];
    int sz, last;
    
    void sa_init()
    {
        sz = last = 0;
        st[0].len = 0;
        st[0].link = -1;
        ++sz;
        // 清除状态:
        for (int i = 0; i < MAXLEN * 2; ++i)
            st[i].next.clear();
    };
    
    void sa_extend(char c)
    {
        int cur = sz++;
        st[cur].len = st[last].len + 1;
        int p;
        for (p = last; p != -1 && !st[p].next.count(c); p = st[p].link)
            st[p].next[c] = cur;
        if (p == -1)
            st[cur].link = 0;
        else
        {
            int q = st[p].next[c];
            if (st[p].len + 1 == st[q].len)
                st[cur].link = q;
            else
            {
                int clone = sz++;
                st[clone].len = st[p].len + 1;
                st[clone].next = st[q].next;
                st[clone].link = st[q].link;
                for (; p != -1 && st[p].next[c] == q; p = st[p].link)
                    st[p].next[c] = clone;
                st[q].link = st[cur].link = clone;
            }
        }
        last = cur;
    };
    
    string lcs(string s, string t)
    {
        sa_init();
        for (int i = 0; i < (int)s.length(); ++i)
            sa_extend(s[i]);
    
        int v = 0, l = 0,
            best = 0, bestpos = 0;
        for (int i = 0; i < (int)t.length(); ++i)
        {
            while (v && !st[v].next.count(t[i]))
            {
                v = st[v].link;
                l = st[v].len;
            }
            if (st[v].next.count(t[i]))
            {
                v = st[v].next[t[i]];
                ++l;
            }
            if (l > best)
                best = l, bestpos = i;
        }
        return t.substr(bestpos - best + 1, best);
    };
    
    static PyObject *sam_lcs(PyObject *self, PyObject *args)
    {
        char *stmp, *ttmp;
        string s, t;
        if (!PyArg_ParseTuple(args, "ss", &stmp, &ttmp))
            return NULL;
        s = stmp;
        t = ttmp;
        return PyUnicode_FromString(lcs(s, t).c_str());
    };
    
    static PyMethodDef sam_lcs_Methods[] = {
        {"lcs", sam_lcs, METH_VARARGS,
         "Get a longest common string of two strings with SAM"},
        {NULL, NULL, 0, NULL}};
    
    static struct PyModuleDef sam = {
        PyModuleDef_HEAD_INIT,
        "sam",
        "SAM",
        -1,
        sam_lcs_Methods};
    
    PyMODINIT_FUNC
    PyInit_sam(void)
    {
        return PyModule_Create(&sam);
    };

    编译安装完成后,就可以在Python里调用了

  • 相关阅读:
    依次逐个亮灯并且每次只能亮一个灯的跑马灯程序
    逐个点亮LED灯,再逐个熄灭LED灯的跑马灯程序---基于74HC595移位锁存器,程序框架用switch语句
    把74HC595驱动程序翻译成类似单片机IO口直接驱动的方式
    两片联级74HC595驱动16个LED灯的基本驱动程序
    树莓派
    Linux I2C驱动
    转:使用 /proc 文件系统来访问 Linux 内核的内容
    转: 使用 /sys 文件系统访问 Linux 内核
    树梅派 -- 通过/sys读写ADC芯片 pcf8591
    树莓派 -- oled 续(2) python
  • 原文地址:https://www.cnblogs.com/shld/p/10456367.html
Copyright © 2020-2023  润新知