This works for me on apache 2.2.16:
RewriteRule ^([a-z]+)/?$ /index.php?p=$1
Here is the rewrite log:
init rewrite engine with requested uri /keyword/
pass through /keyword/
[perdir /var/www/html/] add path info postfix: /var/www/html/keyword -> /var/www/html/keyword/
[perdir /var/www/html/] strip per-dir prefix: /var/www/html/keyword/ -> keyword/
[perdir /var/www/html/] applying pattern '^([a-z]+)/?$' to uri 'keyword/'
[perdir /var/www/html/] rewrite 'keyword/' -> '/index.php?p=keyword'
split uri=/index.php?p=keyword -> uri=/index.php, args=p=keyword
[perdir /var/www/html/] internal redirect with /index.php [INTERNAL REDIRECT]
I'll take this opportunity to correct some of the other answers.
you need the L flag to stop rewriting once the rule has hit. (otherwise you get an endless loop)
This is wrong for two reasons: (1) index.php does not match '^([a-z]+)/?$' and (2) even if it did [L] wouldn't stop the processing because this per-dir rewrite results in an internal redirect (see log) (as they often do) which [L] doesn't stop.
I believe the problem is actually the lack of a forward slash at the beginning of your regular expression.
No, the per-dir rewrite in strips of the initial slash (see log).
RewriteRule %{REQUEST_URI} !.php
This is probably a typo and should be RewriteCond %{REQUEST_URI} !.php
I have no solution but I recommend cranking up the RewriteLogLevel until you can see what is going on.
Edit: I don't think it is mod_rewrite. There is something else in your apache config causing the problem.