算法-25-正则表达式

 

目录

1、定义

1.1、连接操作

1.2、或操作

1.3、闭包操作

1.4、准确定义

2、特殊记号

2.1、空字符串

2.2、括号

2.3、转义字符

3、Java实例

4、正则表达式匹配算法


1、定义

 在我们日常编程中, 使用正则表达式最多的地方就是对账户密码字符的限定了,还有就是在一个文本中查找指定的子字符串。

我们的正则表达式由3种基本操作和作为操作数的字符组成。

1.1、连接操作

我们普通的所有字符串就是连接操作,就比如字符串“ABC” ,A和B和C是相连的并且他们的顺序是确定的,如果你要在一个文本中查找这个字符串,就必须按照它的连接顺序来对比查找。

1.2、或操作

或操作其实就是用我们的或运算符(“|”)来指定的。就比如 “A|BC” 指的是“A” 或者 “BC” 两个子字符串。连接操作优先级高于或操作。

或操作还能用其他记号来扩展。

1、比如“·” 一个点就是表示任意字符的通配符。

2、“[]” 方括号括中的字符,表示你可以拿其中的任何一个字符。

3、如果在方括号中以“^”记号开头,那表示的意思是除了括号中的字符不行,其他字符都可以。

1.3、闭包操作

闭包基本操作可以将模式的部分重复任意的次数。 用(“*”)来标记闭包操作。例如“A*B”就表示0个或者多个A和一个B组成的字符。“ABC*”表示一个AB和0或多个C组成的字符串。

如果你想控制字符的复制次数,可以用以下记号:

1.4、准确定义

一个正则表达式可以是:

  • 空字符串 Є;
  • 单个字符;
  • 包含在括号中的另一个正则表达式;
  • 两个或多个连接起来的正则表达式;
  • 由或运算符分隔的两个或多个正则表达式; 由闭包运算符标记的一个正则表达式。

2、特殊记号

2.1、空字符串

空字符串的记号是“Є”。它存 在于所有文本字符串之中(包括 A*)。

2.2、括号

我们使用括号来改变默认的优先级顺序。例如,C(AC|B)D 指定的语言是 {CACD,CBD},(A|C) ((B|C)D) 指定的语言是 {ABD,CBD,ACD,CCD},(AB)* 指定的语言是由将 AB 连接任意多次得到的 所有字符串和空字符串组成的 {Є,AB,ABAB,...}

2.3、转义字符

我们用“\" 反斜杠来将特殊字符转换成字符本身。就比如“\\”就表示一个"\"。还有一些特殊的转义字符。

3、Java实例

在Java中,我们只要写好正则表达式利用内带的Pattern函数我们就能实现。

    public static void main(String[] args) {
        /**
         * 1、子字符串的查找匹配
         */
        String pat = ".*NEEDLE.*";
        String txt = "A HAYSTACK NEEDLE IN";
        // 方式1:String 的 matches 方法
        boolean isHas1 = txt.matches(pat);
        // 方式2:Pattern 对象的 matches 方法
        boolean isHas2 = Pattern.matches(pat, txt);
        // 方式3: Matcher 对象的 matches 方法
        Pattern p = Pattern.compile(pat);
        Matcher m = p.matcher(txt);
        boolean isHas3 = m.matches();
        System.out.println("txt中是否含有pat1=" + isHas1);
        System.out.println("txt中是否含有pat2=" + isHas2);
        System.out.println("txt中是否含有pat3=" + isHas3);

        /**
         * 账号密码的匹配
         */
        String pat1 = "[0-9]*";
        String txt1="1491984910";
        String txt2="8998aba";

        Pattern p1=Pattern.compile(pat1);
        Matcher m1 = p1.matcher(txt1);
        Matcher m2 = p1.matcher(txt2);

        System.out.println("txt1文本是否符合pat1要求的字符="+m1.matches());
        System.out.println("txt2文本是否符合pat1要求的字符="+m2.matches());
    }

4、正则表达式匹配算法

Digraph----算法-19-有向图(拓扑排序+最短路径)

Stack---算法-2-下压栈(能够自动调整数组大小)

public class NFA {

    private Digraph graph;     // digraph of epsilon transitions
    private String regexp;     // regular expression
    private final int m;       // number of characters in regular expression

    /**
     * Initializes the NFA from the specified regular expression.
     *
     * @param  regexp the regular expression
     */
    public NFA(String regexp) {
        this.regexp = regexp;
        m = regexp.length();
        Stack<Integer> ops = new Stack<Integer>();
        graph = new Digraph(m+1);
        for (int i = 0; i < m; i++) {
            int lp = i;
            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '|')
                ops.push(i);
            else if (regexp.charAt(i) == ')') {
                int or = ops.pop();

                // 2-way or operator
                if (regexp.charAt(or) == '|') {
                    lp = ops.pop();
                    graph.addEdge(lp, or+1);
                    graph.addEdge(or, i);
                }
                else if (regexp.charAt(or) == '(')
                    lp = or;
                else assert false;
            }

            // closure operator (uses 1-character lookahead)
            if (i < m-1 && regexp.charAt(i+1) == '*') {
                graph.addEdge(lp, i+1);
                graph.addEdge(i+1, lp);
            }
            if (regexp.charAt(i) == '(' || regexp.charAt(i) == '*' || regexp.charAt(i) == ')')
                graph.addEdge(i, i+1);
        }
        if (ops.size() != 0)
            throw new IllegalArgumentException("Invalid regular expression");
    }

    /**
     * Returns true if the text is matched by the regular expression.
     *
     * @param  txt the text
     * @return {@code true} if the text is matched by the regular expression,
     *         {@code false} otherwise
     */
    public boolean recognizes(String txt) {
        DirectedDFS dfs = new DirectedDFS(graph, 0);
        Bag<Integer> pc = new Bag<Integer>();
        for (int v = 0; v < graph.V(); v++)
            if (dfs.marked(v)) pc.add(v);

        // Compute possible NFA states for txt[i+1]
        for (int i = 0; i < txt.length(); i++) {
            if (txt.charAt(i) == '*' || txt.charAt(i) == '|' || txt.charAt(i) == '(' || txt.charAt(i) == ')')
                throw new IllegalArgumentException("text contains the metacharacter '" + txt.charAt(i) + "'");

            Bag<Integer> match = new Bag<Integer>();
            for (int v : pc) {
                if (v == m) continue;
                if ((regexp.charAt(v) == txt.charAt(i)) || regexp.charAt(v) == '.')
                    match.add(v+1);
            }
            dfs = new DirectedDFS(graph, match);
            pc = new Bag<Integer>();
            for (int v = 0; v < graph.V(); v++)
                if (dfs.marked(v)) pc.add(v);

            // optimization if no states reachable
            if (pc.size() == 0) return false;
        }

        // check for accept state
        for (int v : pc)
            if (v == m) return true;
        return false;
    }
}
原创文章 120 获赞 34 访问量 28万+

猜你喜欢

转载自blog.csdn.net/qq_34589749/article/details/105074666