0. 写在前面

本文记录了一个AC自动机的诞生!

之前看过有人用C++写过AC自动机,也有用C#写的,还有一个用nodejs写的。。

感觉他们的代码过于冗长,而且AC率也不是很理想。

刚好在回宿舍的路上和学弟聊起这个事

随意想了想思路,觉得还是蛮简单的,就顺手写了一个,效果,还可以接受。

先上个图吧:

最后应该还可以继续刷,如果修改代码或者再添加以下其他搜索引擎可以AC更多题,

不过我有意控制在3000这个AC量,也有意跟在五虎上将之后。

1. 爬虫思路

思路其实非常清晰:

  1. 模拟登录HDU
  2. 针对某一道题目
    • 搜索AC代码

      • 通过正则表达式进行代码的提取
      • 通过htmlparser进行代码的处理
    • 提交
      • 若AC,返回2
      • 否则,继续提交代码(这里最多只提交10份代码)
      • 10次提交后还未AC,放弃此题

2. 简单粗暴的代码

  1. #coding='utf-8'
  2. import requests, re, os, HTMLParser, time, getpass
  3. host_url = 'http://acm.hdu.edu.cn'
  4. post_url = 'http://acm.hdu.edu.cn/userloginex.php?action=login'
  5. sub_url = 'http://acm.hdu.edu.cn/submit.php?action=submit'
  6. csdn_url = 'http://so.csdn.net/so/search/s.do'
  7. head = { 'User-Agent':'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/50.0.2661.94 Safari/537.36' }
  8. html_parser = HTMLParser.HTMLParser()
  9. s = requests.session()
  10. def login(usr,psw):
  11. s.get(host_url);
  12. data = {'username':usr,'userpass':psw,'login':'Sign In'}
  13. r = s.post(post_url,data=data)
  14. def check_lan(lan):
  15. if 'java' in lan:
  16. return '5'
  17. return '0'
  18. def parser_code(code):
  19. return html_parser.unescape(code).encode('utf-8')
  20. def is_ac(pid,usr):
  21. tmp = requests.get('http://acm.hdu.edu.cn/userstatus.php?user='+usr).text
  22. accept = re.search('List of solved problems</font></h3>.*?<p align=left><script language=javascript>(.*?)</script><br></p>',tmp,re.S)
  23. if pid in accept.group(1):
  24. print '%s was solved' %pid
  25. return True
  26. else:
  27. return False
  28. def search_csdn(PID,usr):
  29. get_data = { 'q':'HDU ' + PID, 't':'blog', 'o':'', 's':'', 'l':'null' }
  30. search_html = requests.get(csdn_url,params=get_data).text
  31. linklist = re.findall('<dd class="search-link"><a href="(.*?)" target="_blank">',search_html,re.S)
  32. for l in linklist:
  33. print l
  34. tm_html = requests.get(l,headers=head).text;
  35. title = re.search('<title>(.*?)</title>',tm_html,re.S).group(1).lower()
  36. if PID not in title:
  37. continue
  38. if 'hdu' not in title:
  39. continue
  40. tmp = re.search('name="code" class="(.*?)">(.*?)</pre>',tm_html,re.S)
  41. if tmp == None:
  42. print 'code not find'
  43. continue
  44. LAN = check_lan(tmp.group(1))
  45. CODE = parser_code(tmp.group(2))
  46. if r'include' in CODE:
  47. pass
  48. elif r'import java' in CODE:
  49. pass
  50. else:
  51. continue
  52. print PID, LAN
  53. print '--------------'
  54. submit_data = { 'check':'0', 'problemid':PID, 'language':LAN, 'usercode':CODE }
  55. s.post(sub_url,headers=head,data=submit_data)
  56. time.sleep(5)
  57. if is_ac(PID,usr):
  58. break
  59. if __name__ == '__main__':
  60. usr = raw_input('input your username:')
  61. psw = getpass.getpass('input your password:')
  62. login(usr,psw)
  63. pro_cnt = 1000
  64. while pro_cnt <= 5679:
  65. PID = str(pro_cnt)
  66. if is_ac(PID,usr):
  67. pro_cnt += 1
  68. continue
  69. search_csdn(PID,usr)
  70. pro_cnt += 1

代码不长,仅仅只有78行,是的,就是这样!

3. TDDO

目前没有打算完善这篇博客,也不推荐去研究这个东西,推荐的是去学习真正的算法,哈哈!

很久很久以前自己写过的AC自动机,,,,贴一发:

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. #include <queue>
  5. using namespace std;
  6. #define clr( a, b ) memset( a, b, sizeof(a) )
  7. const int SIGMA_SIZE = 26;
  8. const int NODE_SIZE = 500000 + 10;
  9. struct ac_automaton{
  10. int ch[ NODE_SIZE ][ SIGMA_SIZE ];
  11. int f[ NODE_SIZE ], val[ NODE_SIZE ], last[ NODE_SIZE ];
  12. int sz;
  13. void init(){
  14. sz = 1;
  15. clr( ch[0], 0 ), clr( val, 0 );
  16. }
  17. void insert( char *s ){
  18. int u = 0, i = 0;
  19. for( ; s[i]; ++i ){
  20. int c = s[i] - 'a';
  21. if( !ch[u][c] ){
  22. clr( ch[sz], 0 );
  23. val[sz] = 0;
  24. ch[u][c] = sz++;
  25. }
  26. u = ch[u][c];
  27. }
  28. val[u]++;
  29. }
  30. void getfail(){
  31. queue<int> q;
  32. f[0] = 0;
  33. for( int c = 0; c < SIGMA_SIZE; ++c ){
  34. int u = ch[0][c];
  35. if( u ) f[u] = 0, q.push(u), last[u] = 0;
  36. }
  37. while( !q.empty() ){
  38. int r = q.front(); q.pop();
  39. for( int c = 0; c < SIGMA_SIZE; ++c ){
  40. int u = ch[r][c];
  41. if( !u ){
  42. ch[r][c] = ch[ f[r] ][c];
  43. continue;
  44. }
  45. q.push( u );
  46. int v = f[r];
  47. while( v && !ch[v][c] ) v = f[v];
  48. f[u] = ch[v][c];
  49. last[u] = val[ f[u] ] ? f[u] : last[ f[u] ];
  50. }
  51. }
  52. }
  53. int work( char* s ){
  54. int res = 0;
  55. int u = 0, i = 0, e;
  56. for( ; s[i]; ++i ){
  57. int c = s[i] - 'a';
  58. u = ch[u][c];
  59. e = u;
  60. while( val[e] ){
  61. res += val[e];
  62. val[e] = 0;
  63. e = last[e];
  64. }
  65. }
  66. return res;
  67. }
  68. }ac;

python爬虫学习(11) —— 也写个AC自动机的更多相关文章

  1. python爬虫学习 —— 总目录

    开篇 作为一个C党,接触python之后学习了爬虫. 和AC算法题的快感类似,从网络上爬取各种数据也很有意思. 准备写一系列文章,整理一下学习历程,也给后来者提供一点便利. 我是目录 听说你叫爬虫 - ...

  2. python爬虫学习(1) —— 从urllib说起

    0. 前言 如果你从来没有接触过爬虫,刚开始的时候可能会有些许吃力 因为我不会从头到尾把所有知识点都说一遍,很多文章主要是记录我自己写的一些爬虫 所以建议先学习一下cuiqingcai大神的 Pyth ...

  3. Python爬虫学习:二、爬虫的初步尝试

    我使用的编辑器是IDLE,版本为Python2.7.11,Windows平台. 本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:二.爬虫的初步尝试 1.尝试抓取指定网页 ...

  4. 《Python爬虫学习系列教程》学习笔记

    http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多.学习过程中我把一些学习的笔记总结下来,还记录了一些自己 ...

  5. python爬虫学习笔记(一)——环境配置(windows系统)

    在进行python爬虫学习前,需要进行如下准备工作: python3+pip官方配置 1.Anaconda(推荐,包括python和相关库)   [推荐地址:清华镜像] https://mirrors ...

  6. [转]《Python爬虫学习系列教程》

    <Python爬虫学习系列教程>学习笔记 http://cuiqingcai.com/1052.html 大家好哈,我呢最近在学习Python爬虫,感觉非常有意思,真的让生活可以方便很多. ...

  7. Python爬虫学习02--pyinstaller

    Python爬虫学习02--打包exe可执行程序 1.上一次做了一个爬虫爬取电子书的Python程序,然后发现可以通过pyinstaller进行打包成exe可执行程序.发现非常简单好用 2.这是上次写 ...

  8. Python爬虫学习第一记 (翻译小助手)

    1 # Python爬虫学习第一记 8.24 (代码有点小,请放大看吧) 2 3 #实现有道翻译,模块一: $fanyi.py 4 5 import urllib.request 6 import u ...

  9. Python爬虫学习:三、爬虫的基本操作流程

    本文是博主原创随笔,转载时请注明出处Maple2cat|Python爬虫学习:三.爬虫的基本操作与流程 一般我们使用Python爬虫都是希望实现一套完整的功能,如下: 1.爬虫目标数据.信息: 2.将 ...

随机推荐

  1. Python标准模块--itertools

    1 模块简介 Python提供了itertools模块,可以创建属于自己的迭代器.itertools提供的工具快速并且节约内存.开发者可以使用这些工具创建属于自己特定的迭代器,这些特定的迭代器可以用于 ...

  2. PHP_环境配置_python脚本_2017

    Apache配置 需要安装:VC2015 httpd-2.4.16-win32-VC14.zip VC14就是2015的环境. 又比如:php-5.6.12-Win32-VC11-x86 VC11就是 ...

  3. AFNetworking 3.0 源码解读(二)之 AFSecurityPolicy

    在我们平时的开发中,对网络连接安全方面所做的努力,应该占据很重要的位置. 在解释AFSecurityPolicy之前,我们先把基础的http/https 知识简单的普及一下.获取这方面的信息可通过这本 ...

  4. 2016-Beijing-GDG-DevFest大会参后感

    前话 15年初的时候参加过一次GDG线下举办的一次分享会,因为当时是实习的公司提供的活动场地.有了那次机会后,就一直关注了GDG的活动. 参加的目的最重要的是本次大会是比较盛大的一场技术大会,在经过一 ...

  5. Unity3D中使用委托和事件

    前言: 本来早就想写写和代码设计相关的东西了,以前做2DX的时候就有过写写观察者设计模式的想法,但是实践不多.现在转到U3D的怀抱中,倒是接触了不少委托事件的写法,那干脆就在此总结一下吧. 1.C#中 ...

  6. 如果你也会C#,那不妨了解下F#(4):了解函数及常用函数

    函数式编程其实就是按照数学上的函数运算思想来实现计算机上的运算.虽然我们不需要深入了解数学函数的知识,但应该清楚函数式编程的基础是来自于数学. 例如数学函数\(f(x) = x^2+x\),并没有指定 ...

  7. Hive学习笔记(一)

    摘要: Hive 是建立在 Hadoop 上的数据仓库基础构架.它提供了一系列的工具,可以用来进行数据提取转化加载(ETL),这是一种可以存储.查询和分析存储在 Hadoop 中的大规模数据的机制.H ...

  8. spring/spring boot/spring cloud开发总结

    背景        针对RPC远程调用,都在使用dubbo.dubbox等,我们也是如此.由于社区暂停维护.应对未来发展,我们准备尝试新技术(或许这时候也不算什么新技术了吧),选择使用了spring ...

  9. Effective java笔记(一),创建与销毁对象

    1.考虑用静态工厂方法代替构造器 类的一个实例,通常使用类的公有的构造方法获取.也可以为类提供一个公有的静态工厂方法(不是设计模式中的工厂模式)来返回类的一个实例.例如: //将boolean类型转换 ...

  10. 【工匠大道】Mac下Java开发环境配置简述

    本文地址 原文地址 分享提纲: 1. 下载JDK1.7 2. 配置java_home 3 .安装tomcat 4 .安装eclipse或者myeclipse 5.  mysql安装 破解版下载请参考M ...